Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit aa88e59

Browse files
committed
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.
1 parent d8c4cb7 commit aa88e59

File tree

4 files changed

+107
-91
lines changed

4 files changed

+107
-91
lines changed

src/backend/catalog/heap.c

+68-66
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.158 2001/01/24 19:42:51 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.159 2001/02/12 20:07:21 tgl Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -68,15 +68,15 @@
6868

6969

7070
static void AddNewRelationTuple(Relation pg_class_desc,
71-
Relation new_rel_desc, Oid new_rel_oid,
72-
int natts,
73-
char relkind, char *temp_relname);
71+
Relation new_rel_desc, Oid new_rel_oid, Oid new_type_oid,
72+
int natts, char relkind, char *temp_relname);
7473
static void DeleteAttributeTuples(Relation rel);
7574
static void DeleteRelationTuple(Relation rel);
7675
static void DeleteTypeTuple(Relation rel);
7776
static void RelationRemoveIndexes(Relation relation);
7877
static void RelationRemoveInheritance(Relation relation);
79-
static void AddNewRelationType(char *typeName, Oid new_rel_oid);
78+
static void AddNewRelationType(char *typeName, Oid new_rel_oid,
79+
Oid new_type_oid);
8080
static void StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin,
8181
bool updatePgAttribute);
8282
static void StoreRelCheck(Relation rel, char *ccname, char *ccbin);
@@ -317,6 +317,7 @@ heap_create(char *relname,
317317
strcpy(RelationGetPhysicalRelationName(rel), relname);
318318
rel->rd_rel->relkind = RELKIND_UNCATALOGED;
319319
rel->rd_rel->relnatts = natts;
320+
rel->rd_rel->reltype = InvalidOid;
320321
if (tupDesc->constr)
321322
rel->rd_rel->relchecks = tupDesc->constr->num_check;
322323

@@ -325,12 +326,6 @@ heap_create(char *relname,
325326

326327
RelationGetRelid(rel) = relid;
327328

328-
if (nailme)
329-
{
330-
/* for system relations, set the reltype field here */
331-
rel->rd_rel->reltype = relid;
332-
}
333-
334329
rel->rd_node.tblNode = tblNode;
335330
rel->rd_node.relNode = relid;
336331
rel->rd_rel->relfilenode = relid;
@@ -373,18 +368,17 @@ heap_storage_create(Relation rel)
373368
* performs a scan to ensure that no relation with the
374369
* same name already exists.
375370
*
376-
* 3) heap_create_with_catalog() is called to create the new relation
377-
* on disk.
371+
* 3) heap_create() is called to create the new relation on disk.
378372
*
379-
* 4) TypeDefine() is called to define a new type corresponding
373+
* 4) AddNewRelationTuple() is called to register the
374+
* relation in pg_class.
375+
*
376+
* 5) TypeCreate() is called to define a new type corresponding
380377
* to the new relation.
381378
*
382-
* 5) AddNewAttributeTuples() is called to register the
379+
* 6) AddNewAttributeTuples() is called to register the
383380
* new relation's schema in pg_attribute.
384381
*
385-
* 6) AddNewRelationTuple() is called to register the
386-
* relation itself in the catalogs.
387-
*
388382
* 7) StoreConstraints is called () - vadim 08/22/97
389383
*
390384
* 8) the relations are closed and the new relation's oid
@@ -656,6 +650,7 @@ static void
656650
AddNewRelationTuple(Relation pg_class_desc,
657651
Relation new_rel_desc,
658652
Oid new_rel_oid,
653+
Oid new_type_oid,
659654
int natts,
660655
char relkind,
661656
char *temp_relname)
@@ -665,7 +660,7 @@ AddNewRelationTuple(Relation pg_class_desc,
665660
Relation idescs[Num_pg_class_indices];
666661

667662
/* ----------------
668-
* first we munge some of the information in our
663+
* first we update some of the information in our
669664
* uncataloged relation's relation descriptor.
670665
* ----------------
671666
*/
@@ -694,6 +689,7 @@ AddNewRelationTuple(Relation pg_class_desc,
694689
new_rel_reltup->reltuples = 1000;
695690

696691
new_rel_reltup->relowner = GetUserId();
692+
new_rel_reltup->reltype = new_type_oid;
697693
new_rel_reltup->relkind = relkind;
698694
new_rel_reltup->relnatts = natts;
699695

@@ -705,6 +701,8 @@ AddNewRelationTuple(Relation pg_class_desc,
705701
tup = heap_addheader(Natts_pg_class_fixed,
706702
CLASS_TUPLE_SIZE,
707703
(char *) new_rel_reltup);
704+
705+
/* force tuple to have the desired OID */
708706
tup->t_data->t_oid = new_rel_oid;
709707

710708
/*
@@ -738,10 +736,8 @@ AddNewRelationTuple(Relation pg_class_desc,
738736
* --------------------------------
739737
*/
740738
static void
741-
AddNewRelationType(char *typeName, Oid new_rel_oid)
739+
AddNewRelationType(char *typeName, Oid new_rel_oid, Oid new_type_oid)
742740
{
743-
Oid new_type_oid;
744-
745741
/*
746742
* The sizes are set to oid size because it makes implementing sets
747743
* MUCH easier, and no one (we hope) uses these fields to figure out
@@ -750,23 +746,25 @@ AddNewRelationType(char *typeName, Oid new_rel_oid)
750746
* actually get is the oid of a tuple in the pg_proc catalog, so the
751747
* size of the "set" is the size of an oid. Similarly, byval being
752748
* true makes sets much easier, and it isn't used by anything else.
753-
* Note the assumption that OIDs are the same size as int4s.
754-
*/
755-
new_type_oid = TypeCreate(typeName, /* type name */
756-
new_rel_oid, /* relation oid */
757-
sizeof(Oid), /* internal size */
758-
sizeof(Oid), /* external size */
759-
'c', /* type-type (catalog) */
760-
',', /* default array delimiter */
761-
"int4in", /* input procedure */
762-
"int4out", /* output procedure */
763-
"int4in", /* receive procedure */
764-
"int4out", /* send procedure */
765-
NULL, /* array element type - irrelevent */
766-
"-", /* default type value */
767-
(bool) 1, /* passed by value */
768-
'i', /* default alignment */
769-
'p'); /* Not TOASTable */
749+
*
750+
* XXX Note the assumption that OIDs are the same size as int4s.
751+
*/
752+
TypeCreate(typeName, /* type name */
753+
new_type_oid, /* preassigned oid for type */
754+
new_rel_oid, /* relation oid */
755+
sizeof(Oid), /* internal size */
756+
sizeof(Oid), /* external size */
757+
'c', /* type-type (catalog) */
758+
',', /* default array delimiter */
759+
"int4in", /* input procedure */
760+
"int4out", /* output procedure */
761+
"int4in", /* receive procedure */
762+
"int4out", /* send procedure */
763+
NULL, /* array element type - irrelevant */
764+
"-", /* default type value */
765+
true, /* passed by value */
766+
'i', /* default alignment */
767+
'p'); /* Not TOASTable */
770768
}
771769

772770
/* --------------------------------
@@ -785,6 +783,7 @@ heap_create_with_catalog(char *relname,
785783
Relation pg_class_desc;
786784
Relation new_rel_desc;
787785
Oid new_rel_oid;
786+
Oid new_type_oid;
788787
int natts = tupdesc->natts;
789788
char *temp_relname = NULL;
790789

@@ -814,18 +813,10 @@ heap_create_with_catalog(char *relname,
814813
}
815814

816815
/* ----------------
817-
* RelnameFindRelid couldn't detect simultaneous
818-
* creation. Uniqueness will be really checked by unique
819-
* indexes of system tables but we couldn't check it here.
820-
* We have to postpone creating the disk file for this
821-
* relation.
822-
* Another boolean parameter "storage_create" was added
823-
* to heap_create() function. If the parameter is false
824-
* heap_create() only registers an uncataloged relation
825-
* to relation cache and heap_storage_create() should be
826-
* called later.
827-
* We could pull its relation oid from the newly formed
828-
* relation descriptor.
816+
* Tell heap_create not to create a physical file; we'll do that
817+
* below after all our catalog updates are done. (This isn't really
818+
* necessary anymore, but we may as well avoid the cycles of creating
819+
* and deleting the file in case we fail.)
829820
*
830821
* Note: The call to heap_create() changes relname for
831822
* temp tables; it becomes the true physical relname.
@@ -836,35 +827,47 @@ heap_create_with_catalog(char *relname,
836827
new_rel_desc = heap_create(relname, tupdesc, istemp, false,
837828
allow_system_table_mods);
838829

830+
/* Fetch the relation OID assigned by heap_create */
839831
new_rel_oid = new_rel_desc->rd_att->attrs[0]->attrelid;
840832

841-
/* ----------------
842-
* since defining a relation also defines a complex type,
843-
* we add a new system type corresponding to the new relation.
844-
* ----------------
845-
*/
846-
AddNewRelationType(relname, new_rel_oid);
833+
/* Assign an OID for the relation's tuple type */
834+
new_type_oid = newoid();
847835

848836
/* ----------------
849-
* now add tuples to pg_attribute for the attributes in
850-
* our new relation.
851-
* ----------------
852-
*/
853-
AddNewAttributeTuples(new_rel_oid, tupdesc);
854-
855-
/* ----------------
856-
* now update the information in pg_class.
837+
* now create an entry in pg_class for the relation.
838+
*
839+
* NOTE: we could get a unique-index failure here, in case someone else
840+
* is creating the same relation name in parallel but hadn't committed
841+
* yet when we checked for a duplicate name above.
857842
* ----------------
858843
*/
859844
pg_class_desc = heap_openr(RelationRelationName, RowExclusiveLock);
860845

861846
AddNewRelationTuple(pg_class_desc,
862847
new_rel_desc,
863848
new_rel_oid,
849+
new_type_oid,
864850
natts,
865851
relkind,
866852
temp_relname);
867853

854+
/* ----------------
855+
* since defining a relation also defines a complex type,
856+
* we add a new system type corresponding to the new relation.
857+
*
858+
* NOTE: we could get a unique-index failure here, in case the same name
859+
* has already been used for a type.
860+
* ----------------
861+
*/
862+
AddNewRelationType(relname, new_rel_oid, new_type_oid);
863+
864+
/* ----------------
865+
* now add tuples to pg_attribute for the attributes in
866+
* our new relation.
867+
* ----------------
868+
*/
869+
AddNewAttributeTuples(new_rel_oid, tupdesc);
870+
868871
StoreConstraints(new_rel_desc);
869872

870873
if (istemp)
@@ -912,7 +915,6 @@ heap_create_with_catalog(char *relname,
912915
* attribute catalog (needed?). (Anything else?)
913916
*
914917
* get proper relation from relation catalog (if not arg)
915-
* check if relation is vital (strcmp()/reltype?)
916918
* scan attribute catalog deleting attributes of reldesc
917919
* (necessary?)
918920
* delete relation from relation catalog

src/backend/catalog/pg_type.c

+31-21
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.58 2001/01/24 19:42:52 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_type.c,v 1.59 2001/02/12 20:07:21 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -46,18 +46,17 @@ TypeGetWithOpenRelation(Relation pg_type_desc,
4646
HeapScanDesc scan;
4747
HeapTuple tup;
4848
Oid typoid;
49-
50-
static ScanKeyData typeKey[1] = {
51-
{0, Anum_pg_type_typname, F_NAMEEQ}
52-
};
49+
ScanKeyData typeKey[1];
5350

5451
/* ----------------
5552
* initialize the scan key and begin a scan of pg_type
5653
* ----------------
5754
*/
58-
fmgr_info(F_NAMEEQ, &typeKey[0].sk_func);
59-
typeKey[0].sk_nargs = typeKey[0].sk_func.fn_nargs;
60-
typeKey[0].sk_argument = PointerGetDatum(typeName);
55+
ScanKeyEntryInitialize(typeKey,
56+
0,
57+
Anum_pg_type_typname,
58+
F_NAMEEQ,
59+
PointerGetDatum(typeName));
6160

6261
scan = heap_beginscan(pg_type_desc,
6362
0,
@@ -269,10 +268,16 @@ TypeShellMake(char *typeName)
269268
* TypeCreate
270269
*
271270
* This does all the necessary work needed to define a new type.
271+
*
272+
* NOTE: if assignedTypeOid is not InvalidOid, then that OID is assigned to
273+
* the new type (which, therefore, cannot already exist as a shell type).
274+
* This hack is only intended for use in creating a relation's associated
275+
* type, where we need to have created the relation tuple already.
272276
* ----------------------------------------------------------------
273277
*/
274278
Oid
275279
TypeCreate(char *typeName,
280+
Oid assignedTypeOid,
276281
Oid relationOid, /* only for 'c'atalog typeTypes */
277282
int16 internalSize,
278283
int16 externalSize,
@@ -292,35 +297,28 @@ TypeCreate(char *typeName,
292297
j;
293298
Relation pg_type_desc;
294299
HeapScanDesc pg_type_scan;
295-
296300
Oid typeObjectId;
297301
Oid elementObjectId = InvalidOid;
298-
299302
HeapTuple tup;
300303
char nulls[Natts_pg_type];
301304
char replaces[Natts_pg_type];
302305
Datum values[Natts_pg_type];
303-
304306
char *procname;
305307
char *procs[4];
306308
bool defined;
307309
NameData name;
308310
TupleDesc tupDesc;
309311
Oid argList[FUNC_MAX_ARGS];
310-
311-
static ScanKeyData typeKey[1] = {
312-
{0, Anum_pg_type_typname, F_NAMEEQ}
313-
};
314-
315-
fmgr_info(F_NAMEEQ, &typeKey[0].sk_func);
316-
typeKey[0].sk_nargs = typeKey[0].sk_func.fn_nargs;
312+
ScanKeyData typeKey[1];
317313

318314
/* ----------------
319-
* check that the type is not already defined.
315+
* check that the type is not already defined. It might exist as
316+
* a shell type, however (but only if assignedTypeOid is not given).
320317
* ----------------
321318
*/
322319
typeObjectId = TypeGet(typeName, &defined);
323-
if (OidIsValid(typeObjectId) && defined)
320+
if (OidIsValid(typeObjectId) &&
321+
(defined || assignedTypeOid != InvalidOid))
324322
elog(ERROR, "TypeCreate: type %s already defined", typeName);
325323

326324
/* ----------------
@@ -468,7 +466,12 @@ TypeCreate(char *typeName,
468466
*/
469467
pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock);
470468

471-
typeKey[0].sk_argument = PointerGetDatum(typeName);
469+
ScanKeyEntryInitialize(typeKey,
470+
0,
471+
Anum_pg_type_typname,
472+
F_NAMEEQ,
473+
PointerGetDatum(typeName));
474+
472475
pg_type_scan = heap_beginscan(pg_type_desc,
473476
0,
474477
SnapshotSelf, /* cache? */
@@ -484,6 +487,10 @@ TypeCreate(char *typeName,
484487
tup = heap_getnext(pg_type_scan, 0);
485488
if (HeapTupleIsValid(tup))
486489
{
490+
/* should not happen given prior test? */
491+
if (assignedTypeOid != InvalidOid)
492+
elog(ERROR, "TypeCreate: type %s already defined", typeName);
493+
487494
tup = heap_modifytuple(tup,
488495
pg_type_desc,
489496
values,
@@ -502,6 +509,9 @@ TypeCreate(char *typeName,
502509
values,
503510
nulls);
504511

512+
/* preassign tuple Oid, if one was given */
513+
tup->t_data->t_oid = assignedTypeOid;
514+
505515
heap_insert(pg_type_desc, tup);
506516

507517
typeObjectId = tup->t_data->t_oid;

0 commit comments

Comments
 (0)