*
*
* 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
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);
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;
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;
* 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
AddNewRelationTuple(Relation pg_class_desc,
Relation new_rel_desc,
Oid new_rel_oid,
+ Oid new_type_oid,
int natts,
char relkind,
char *temp_relname)
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.
* ----------------
*/
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;
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;
/*
* --------------------------------
*/
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
* 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.
- */
- 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 */
+ *
+ * XXX Note the assumption that OIDs are the same size as int4s.
+ */
+ 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 */
}
/* --------------------------------
Relation pg_class_desc;
Relation new_rel_desc;
Oid new_rel_oid;
+ Oid new_type_oid;
int natts = tupdesc->natts;
char *temp_relname = NULL;
}
/* ----------------
- * 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.
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);
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)
* 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
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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,
* 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,
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);
/* ----------------
*/
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? */
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,
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;