Commit aa88e59a authored by Tom Lane's avatar Tom Lane

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.
parent d8c4cb74
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * INTERFACE ROUTINES
...@@ -68,15 +68,15 @@ ...@@ -68,15 +68,15 @@
static void AddNewRelationTuple(Relation pg_class_desc, static void AddNewRelationTuple(Relation pg_class_desc,
Relation new_rel_desc, Oid new_rel_oid, Relation new_rel_desc, Oid new_rel_oid, Oid new_type_oid,
int natts, int natts, char relkind, char *temp_relname);
char relkind, char *temp_relname);
static void DeleteAttributeTuples(Relation rel); static void DeleteAttributeTuples(Relation rel);
static void DeleteRelationTuple(Relation rel); static void DeleteRelationTuple(Relation rel);
static void DeleteTypeTuple(Relation rel); static void DeleteTypeTuple(Relation rel);
static void RelationRemoveIndexes(Relation relation); static void RelationRemoveIndexes(Relation relation);
static void RelationRemoveInheritance(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, static void StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin,
bool updatePgAttribute); bool updatePgAttribute);
static void StoreRelCheck(Relation rel, char *ccname, char *ccbin); static void StoreRelCheck(Relation rel, char *ccname, char *ccbin);
...@@ -317,6 +317,7 @@ heap_create(char *relname, ...@@ -317,6 +317,7 @@ heap_create(char *relname,
strcpy(RelationGetPhysicalRelationName(rel), relname); strcpy(RelationGetPhysicalRelationName(rel), relname);
rel->rd_rel->relkind = RELKIND_UNCATALOGED; rel->rd_rel->relkind = RELKIND_UNCATALOGED;
rel->rd_rel->relnatts = natts; rel->rd_rel->relnatts = natts;
rel->rd_rel->reltype = InvalidOid;
if (tupDesc->constr) if (tupDesc->constr)
rel->rd_rel->relchecks = tupDesc->constr->num_check; rel->rd_rel->relchecks = tupDesc->constr->num_check;
...@@ -325,12 +326,6 @@ heap_create(char *relname, ...@@ -325,12 +326,6 @@ heap_create(char *relname,
RelationGetRelid(rel) = relid; 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.tblNode = tblNode;
rel->rd_node.relNode = relid; rel->rd_node.relNode = relid;
rel->rd_rel->relfilenode = relid; rel->rd_rel->relfilenode = relid;
...@@ -373,18 +368,17 @@ heap_storage_create(Relation rel) ...@@ -373,18 +368,17 @@ heap_storage_create(Relation rel)
* performs a scan to ensure that no relation with the * performs a scan to ensure that no relation with the
* same name already exists. * same name already exists.
* *
* 3) heap_create_with_catalog() is called to create the new relation * 3) heap_create() is called to create the new relation on disk.
* 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. * 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. * 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 * 7) StoreConstraints is called () - vadim 08/22/97
* *
* 8) the relations are closed and the new relation's oid * 8) the relations are closed and the new relation's oid
...@@ -656,6 +650,7 @@ static void ...@@ -656,6 +650,7 @@ static void
AddNewRelationTuple(Relation pg_class_desc, AddNewRelationTuple(Relation pg_class_desc,
Relation new_rel_desc, Relation new_rel_desc,
Oid new_rel_oid, Oid new_rel_oid,
Oid new_type_oid,
int natts, int natts,
char relkind, char relkind,
char *temp_relname) char *temp_relname)
...@@ -665,7 +660,7 @@ AddNewRelationTuple(Relation pg_class_desc, ...@@ -665,7 +660,7 @@ AddNewRelationTuple(Relation pg_class_desc,
Relation idescs[Num_pg_class_indices]; 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. * uncataloged relation's relation descriptor.
* ---------------- * ----------------
*/ */
...@@ -694,6 +689,7 @@ AddNewRelationTuple(Relation pg_class_desc, ...@@ -694,6 +689,7 @@ AddNewRelationTuple(Relation pg_class_desc,
new_rel_reltup->reltuples = 1000; new_rel_reltup->reltuples = 1000;
new_rel_reltup->relowner = GetUserId(); new_rel_reltup->relowner = GetUserId();
new_rel_reltup->reltype = new_type_oid;
new_rel_reltup->relkind = relkind; new_rel_reltup->relkind = relkind;
new_rel_reltup->relnatts = natts; new_rel_reltup->relnatts = natts;
...@@ -705,6 +701,8 @@ AddNewRelationTuple(Relation pg_class_desc, ...@@ -705,6 +701,8 @@ AddNewRelationTuple(Relation pg_class_desc,
tup = heap_addheader(Natts_pg_class_fixed, tup = heap_addheader(Natts_pg_class_fixed,
CLASS_TUPLE_SIZE, CLASS_TUPLE_SIZE,
(char *) new_rel_reltup); (char *) new_rel_reltup);
/* force tuple to have the desired OID */
tup->t_data->t_oid = new_rel_oid; tup->t_data->t_oid = new_rel_oid;
/* /*
...@@ -738,10 +736,8 @@ AddNewRelationTuple(Relation pg_class_desc, ...@@ -738,10 +736,8 @@ AddNewRelationTuple(Relation pg_class_desc,
* -------------------------------- * --------------------------------
*/ */
static void 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 * 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 * MUCH easier, and no one (we hope) uses these fields to figure out
...@@ -750,9 +746,11 @@ AddNewRelationType(char *typeName, Oid new_rel_oid) ...@@ -750,9 +746,11 @@ AddNewRelationType(char *typeName, Oid new_rel_oid)
* actually get is the oid of a tuple in the pg_proc catalog, so the * 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 * 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. * 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 */ TypeCreate(typeName, /* type name */
new_type_oid, /* preassigned oid for type */
new_rel_oid, /* relation oid */ new_rel_oid, /* relation oid */
sizeof(Oid), /* internal size */ sizeof(Oid), /* internal size */
sizeof(Oid), /* external size */ sizeof(Oid), /* external size */
...@@ -762,9 +760,9 @@ AddNewRelationType(char *typeName, Oid new_rel_oid) ...@@ -762,9 +760,9 @@ AddNewRelationType(char *typeName, Oid new_rel_oid)
"int4out", /* output procedure */ "int4out", /* output procedure */
"int4in", /* receive procedure */ "int4in", /* receive procedure */
"int4out", /* send procedure */ "int4out", /* send procedure */
NULL, /* array element type - irrelevent */ NULL, /* array element type - irrelevant */
"-", /* default type value */ "-", /* default type value */
(bool) 1, /* passed by value */ true, /* passed by value */
'i', /* default alignment */ 'i', /* default alignment */
'p'); /* Not TOASTable */ 'p'); /* Not TOASTable */
} }
...@@ -785,6 +783,7 @@ heap_create_with_catalog(char *relname, ...@@ -785,6 +783,7 @@ heap_create_with_catalog(char *relname,
Relation pg_class_desc; Relation pg_class_desc;
Relation new_rel_desc; Relation new_rel_desc;
Oid new_rel_oid; Oid new_rel_oid;
Oid new_type_oid;
int natts = tupdesc->natts; int natts = tupdesc->natts;
char *temp_relname = NULL; char *temp_relname = NULL;
...@@ -814,18 +813,10 @@ heap_create_with_catalog(char *relname, ...@@ -814,18 +813,10 @@ heap_create_with_catalog(char *relname,
} }
/* ---------------- /* ----------------
* RelnameFindRelid couldn't detect simultaneous * Tell heap_create not to create a physical file; we'll do that
* creation. Uniqueness will be really checked by unique * below after all our catalog updates are done. (This isn't really
* indexes of system tables but we couldn't check it here. * necessary anymore, but we may as well avoid the cycles of creating
* We have to postpone creating the disk file for this * and deleting the file in case we fail.)
* 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.
* *
* Note: The call to heap_create() changes relname for * Note: The call to heap_create() changes relname for
* temp tables; it becomes the true physical relname. * temp tables; it becomes the true physical relname.
...@@ -836,24 +827,18 @@ heap_create_with_catalog(char *relname, ...@@ -836,24 +827,18 @@ heap_create_with_catalog(char *relname,
new_rel_desc = heap_create(relname, tupdesc, istemp, false, new_rel_desc = heap_create(relname, tupdesc, istemp, false,
allow_system_table_mods); allow_system_table_mods);
/* Fetch the relation OID assigned by heap_create */
new_rel_oid = new_rel_desc->rd_att->attrs[0]->attrelid; new_rel_oid = new_rel_desc->rd_att->attrs[0]->attrelid;
/* ---------------- /* Assign an OID for the relation's tuple type */
* since defining a relation also defines a complex type, new_type_oid = newoid();
* we add a new system type corresponding to the new relation.
* ----------------
*/
AddNewRelationType(relname, new_rel_oid);
/* ---------------- /* ----------------
* now add tuples to pg_attribute for the attributes in * now create an entry in pg_class for the relation.
* our new 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
AddNewAttributeTuples(new_rel_oid, tupdesc); * yet when we checked for a duplicate name above.
/* ----------------
* now update the information in pg_class.
* ---------------- * ----------------
*/ */
pg_class_desc = heap_openr(RelationRelationName, RowExclusiveLock); pg_class_desc = heap_openr(RelationRelationName, RowExclusiveLock);
...@@ -861,10 +846,28 @@ heap_create_with_catalog(char *relname, ...@@ -861,10 +846,28 @@ heap_create_with_catalog(char *relname,
AddNewRelationTuple(pg_class_desc, AddNewRelationTuple(pg_class_desc,
new_rel_desc, new_rel_desc,
new_rel_oid, new_rel_oid,
new_type_oid,
natts, natts,
relkind, relkind,
temp_relname); 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); StoreConstraints(new_rel_desc);
if (istemp) if (istemp)
...@@ -912,7 +915,6 @@ heap_create_with_catalog(char *relname, ...@@ -912,7 +915,6 @@ heap_create_with_catalog(char *relname,
* attribute catalog (needed?). (Anything else?) * attribute catalog (needed?). (Anything else?)
* *
* get proper relation from relation catalog (if not arg) * get proper relation from relation catalog (if not arg)
* check if relation is vital (strcmp()/reltype?)
* scan attribute catalog deleting attributes of reldesc * scan attribute catalog deleting attributes of reldesc
* (necessary?) * (necessary?)
* delete relation from relation catalog * delete relation from relation catalog
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -46,18 +46,17 @@ TypeGetWithOpenRelation(Relation pg_type_desc,
HeapScanDesc scan; HeapScanDesc scan;
HeapTuple tup; HeapTuple tup;
Oid typoid; Oid typoid;
ScanKeyData typeKey[1];
static ScanKeyData typeKey[1] = {
{0, Anum_pg_type_typname, F_NAMEEQ}
};
/* ---------------- /* ----------------
* initialize the scan key and begin a scan of pg_type * initialize the scan key and begin a scan of pg_type
* ---------------- * ----------------
*/ */
fmgr_info(F_NAMEEQ, &typeKey[0].sk_func); ScanKeyEntryInitialize(typeKey,
typeKey[0].sk_nargs = typeKey[0].sk_func.fn_nargs; 0,
typeKey[0].sk_argument = PointerGetDatum(typeName); Anum_pg_type_typname,
F_NAMEEQ,
PointerGetDatum(typeName));
scan = heap_beginscan(pg_type_desc, scan = heap_beginscan(pg_type_desc,
0, 0,
...@@ -269,10 +268,16 @@ TypeShellMake(char *typeName) ...@@ -269,10 +268,16 @@ TypeShellMake(char *typeName)
* TypeCreate * TypeCreate
* *
* This does all the necessary work needed to define a new type. * 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 Oid
TypeCreate(char *typeName, TypeCreate(char *typeName,
Oid assignedTypeOid,
Oid relationOid, /* only for 'c'atalog typeTypes */ Oid relationOid, /* only for 'c'atalog typeTypes */
int16 internalSize, int16 internalSize,
int16 externalSize, int16 externalSize,
...@@ -292,35 +297,28 @@ TypeCreate(char *typeName, ...@@ -292,35 +297,28 @@ TypeCreate(char *typeName,
j; j;
Relation pg_type_desc; Relation pg_type_desc;
HeapScanDesc pg_type_scan; HeapScanDesc pg_type_scan;
Oid typeObjectId; Oid typeObjectId;
Oid elementObjectId = InvalidOid; Oid elementObjectId = InvalidOid;
HeapTuple tup; HeapTuple tup;
char nulls[Natts_pg_type]; char nulls[Natts_pg_type];
char replaces[Natts_pg_type]; char replaces[Natts_pg_type];
Datum values[Natts_pg_type]; Datum values[Natts_pg_type];
char *procname; char *procname;
char *procs[4]; char *procs[4];
bool defined; bool defined;
NameData name; NameData name;
TupleDesc tupDesc; TupleDesc tupDesc;
Oid argList[FUNC_MAX_ARGS]; Oid argList[FUNC_MAX_ARGS];
ScanKeyData typeKey[1];
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;
/* ---------------- /* ----------------
* 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); typeObjectId = TypeGet(typeName, &defined);
if (OidIsValid(typeObjectId) && defined) if (OidIsValid(typeObjectId) &&
(defined || assignedTypeOid != InvalidOid))
elog(ERROR, "TypeCreate: type %s already defined", typeName); elog(ERROR, "TypeCreate: type %s already defined", typeName);
/* ---------------- /* ----------------
...@@ -468,7 +466,12 @@ TypeCreate(char *typeName, ...@@ -468,7 +466,12 @@ TypeCreate(char *typeName,
*/ */
pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock); 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, pg_type_scan = heap_beginscan(pg_type_desc,
0, 0,
SnapshotSelf, /* cache? */ SnapshotSelf, /* cache? */
...@@ -484,6 +487,10 @@ TypeCreate(char *typeName, ...@@ -484,6 +487,10 @@ TypeCreate(char *typeName,
tup = heap_getnext(pg_type_scan, 0); tup = heap_getnext(pg_type_scan, 0);
if (HeapTupleIsValid(tup)) if (HeapTupleIsValid(tup))
{ {
/* should not happen given prior test? */
if (assignedTypeOid != InvalidOid)
elog(ERROR, "TypeCreate: type %s already defined", typeName);
tup = heap_modifytuple(tup, tup = heap_modifytuple(tup,
pg_type_desc, pg_type_desc,
values, values,
...@@ -502,6 +509,9 @@ TypeCreate(char *typeName, ...@@ -502,6 +509,9 @@ TypeCreate(char *typeName,
values, values,
nulls); nulls);
/* preassign tuple Oid, if one was given */
tup->t_data->t_oid = assignedTypeOid;
heap_insert(pg_type_desc, tup); heap_insert(pg_type_desc, tup);
typeObjectId = tup->t_data->t_oid; typeObjectId = tup->t_data->t_oid;
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * 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 * DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the * The "DefineFoo" routines take the parse tree and pick out the
...@@ -640,6 +640,7 @@ DefineType(char *typeName, List *parameters) ...@@ -640,6 +640,7 @@ DefineType(char *typeName, List *parameters)
* ---------------- * ----------------
*/ */
TypeCreate(typeName, /* type name */ TypeCreate(typeName, /* type name */
InvalidOid, /* preassigned type oid (not done here) */
InvalidOid, /* relation oid (n/a here) */ InvalidOid, /* relation oid (n/a here) */
internalLength, /* internal size */ internalLength, /* internal size */
externalLength, /* external size */ externalLength, /* external size */
...@@ -652,7 +653,7 @@ DefineType(char *typeName, List *parameters) ...@@ -652,7 +653,7 @@ DefineType(char *typeName, List *parameters)
elemName, /* element type name */ elemName, /* element type name */
defaultValue, /* default type value */ defaultValue, /* default type value */
byValue, /* passed by value */ byValue, /* passed by value */
alignment, alignment, /* required alignment */
storage); /* TOAST strategy */ storage); /* TOAST strategy */
/* ---------------- /* ----------------
...@@ -663,6 +664,7 @@ DefineType(char *typeName, List *parameters) ...@@ -663,6 +664,7 @@ DefineType(char *typeName, List *parameters)
shadow_type = makeArrayTypeName(typeName); shadow_type = makeArrayTypeName(typeName);
TypeCreate(shadow_type, /* type name */ TypeCreate(shadow_type, /* type name */
InvalidOid, /* preassigned type oid (not done here) */
InvalidOid, /* relation oid (n/a here) */ InvalidOid, /* relation oid (n/a here) */
-1, /* internal size */ -1, /* internal size */
-1, /* external size */ -1, /* external size */
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 * NOTES
* the genbki.sh script reads this file and generates .bki * the genbki.sh script reads this file and generates .bki
...@@ -420,6 +420,7 @@ DESCR("numeric(precision, decimal), arbitrary precision number"); ...@@ -420,6 +420,7 @@ DESCR("numeric(precision, decimal), arbitrary precision number");
extern Oid TypeGet(char *typeName, bool *defined); extern Oid TypeGet(char *typeName, bool *defined);
extern Oid TypeShellMake(char *typeName); extern Oid TypeShellMake(char *typeName);
extern Oid TypeCreate(char *typeName, extern Oid TypeCreate(char *typeName,
Oid assignedTypeOid,
Oid relationOid, Oid relationOid,
int16 internalSize, int16 internalSize,
int16 externalSize, int16 externalSize,
...@@ -431,7 +432,8 @@ extern Oid TypeCreate(char *typeName, ...@@ -431,7 +432,8 @@ extern Oid TypeCreate(char *typeName,
char *sendProcedure, char *sendProcedure,
char *elementTypeName, char *elementTypeName,
char *defaultTypeValue, char *defaultTypeValue,
bool passedByValue, char alignment, bool passedByValue,
char alignment,
char storage); char storage);
extern void TypeRename(const char *oldTypeName, const char *newTypeName); extern void TypeRename(const char *oldTypeName, const char *newTypeName);
extern char *makeArrayTypeName(char *typeName); extern char *makeArrayTypeName(char *typeName);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment