Skip to content

Commit e1a5e65

Browse files
committed
Convert Typ from array to list in bootstrap
It's a bit easier and more convenient to free and reload a List, compared to a plain array. This will be helpful when allowing catalogs to contain composite types. Author: Justin Pryzby Reviewed-by: Dean Rasheed, Tomas Vondra Discussion: https://postgr.es/m/ad7891d2-e90c-b446-9fe2-7419143847d7%40enterprisedb.com
1 parent 5b861ba commit e1a5e65

File tree

1 file changed

+41
-48
lines changed

1 file changed

+41
-48
lines changed

src/backend/bootstrap/bootstrap.c

Lines changed: 41 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ static void BootstrapModeMain(void);
5959
static void bootstrap_signals(void);
6060
static void ShutdownAuxiliaryProcess(int code, Datum arg);
6161
static Form_pg_attribute AllocateAttribute(void);
62-
static void populate_typ_array(void);
62+
static void populate_typ_list(void);
6363
static Oid gettype(char *type);
6464
static void cleanup(void);
6565

@@ -160,7 +160,7 @@ struct typmap
160160
FormData_pg_type am_typ;
161161
};
162162

163-
static struct typmap **Typ = NULL;
163+
static List *Typ = NIL; /* List of struct typmap* */
164164
static struct typmap *Ap = NULL;
165165

166166
static Datum values[MAXATTR]; /* current row's attribute values */
@@ -598,10 +598,10 @@ boot_openrel(char *relname)
598598

599599
/*
600600
* pg_type must be filled before any OPEN command is executed, hence we
601-
* can now populate the Typ array if we haven't yet.
601+
* can now populate Typ if we haven't yet.
602602
*/
603-
if (Typ == NULL)
604-
populate_typ_array();
603+
if (Typ == NIL)
604+
populate_typ_list();
605605

606606
if (boot_reldesc != NULL)
607607
closerel(NULL);
@@ -691,7 +691,7 @@ DefineAttr(char *name, char *type, int attnum, int nullness)
691691

692692
typeoid = gettype(type);
693693

694-
if (Typ != NULL)
694+
if (Typ != NIL)
695695
{
696696
attrtypes[attnum]->atttypid = Ap->am_oid;
697697
attrtypes[attnum]->attlen = Ap->am_typ.typlen;
@@ -873,47 +873,36 @@ cleanup(void)
873873
}
874874

875875
/* ----------------
876-
* populate_typ_array
876+
* populate_typ_list
877877
*
878-
* Load the Typ array by reading pg_type.
878+
* Load the Typ list by reading pg_type.
879879
* ----------------
880880
*/
881881
static void
882-
populate_typ_array(void)
882+
populate_typ_list(void)
883883
{
884884
Relation rel;
885885
TableScanDesc scan;
886886
HeapTuple tup;
887-
int nalloc;
888-
int i;
889-
890-
Assert(Typ == NULL);
887+
MemoryContext old;
891888

892-
nalloc = 512;
893-
Typ = (struct typmap **)
894-
MemoryContextAlloc(TopMemoryContext, nalloc * sizeof(struct typmap *));
889+
Assert(Typ == NIL);
895890

896891
rel = table_open(TypeRelationId, NoLock);
897892
scan = table_beginscan_catalog(rel, 0, NULL);
898-
i = 0;
893+
old = MemoryContextSwitchTo(TopMemoryContext);
899894
while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
900895
{
901896
Form_pg_type typForm = (Form_pg_type) GETSTRUCT(tup);
897+
struct typmap *newtyp;
902898

903-
/* make sure there will be room for a trailing NULL pointer */
904-
if (i >= nalloc - 1)
905-
{
906-
nalloc *= 2;
907-
Typ = (struct typmap **)
908-
repalloc(Typ, nalloc * sizeof(struct typmap *));
909-
}
910-
Typ[i] = (struct typmap *)
911-
MemoryContextAlloc(TopMemoryContext, sizeof(struct typmap));
912-
Typ[i]->am_oid = typForm->oid;
913-
memcpy(&(Typ[i]->am_typ), typForm, sizeof(Typ[i]->am_typ));
914-
i++;
899+
newtyp = (struct typmap *) palloc(sizeof(struct typmap));
900+
Typ = lappend(Typ, newtyp);
901+
902+
newtyp->am_oid = typForm->oid;
903+
memcpy(&newtyp->am_typ, typForm, sizeof(newtyp->am_typ));
915904
}
916-
Typ[i] = NULL; /* Fill trailing NULL pointer */
905+
MemoryContextSwitchTo(old);
917906
table_endscan(scan);
918907
table_close(rel, NoLock);
919908
}
@@ -923,25 +912,26 @@ populate_typ_array(void)
923912
*
924913
* NB: this is really ugly; it will return an integer index into TypInfo[],
925914
* and not an OID at all, until the first reference to a type not known in
926-
* TypInfo[]. At that point it will read and cache pg_type in the Typ array,
915+
* TypInfo[]. At that point it will read and cache pg_type in Typ,
927916
* and subsequently return a real OID (and set the global pointer Ap to
928917
* point at the found row in Typ). So caller must check whether Typ is
929-
* still NULL to determine what the return value is!
918+
* still NIL to determine what the return value is!
930919
* ----------------
931920
*/
932921
static Oid
933922
gettype(char *type)
934923
{
935-
if (Typ != NULL)
924+
if (Typ != NIL)
936925
{
937-
struct typmap **app;
926+
ListCell *lc;
938927

939-
for (app = Typ; *app != NULL; app++)
928+
foreach (lc, Typ)
940929
{
941-
if (strncmp(NameStr((*app)->am_typ.typname), type, NAMEDATALEN) == 0)
930+
struct typmap *app = lfirst(lc);
931+
if (strncmp(NameStr(app->am_typ.typname), type, NAMEDATALEN) == 0)
942932
{
943-
Ap = *app;
944-
return (*app)->am_oid;
933+
Ap = app;
934+
return app->am_oid;
945935
}
946936
}
947937
}
@@ -956,7 +946,7 @@ gettype(char *type)
956946
}
957947
/* Not in TypInfo, so we'd better be able to read pg_type now */
958948
elog(DEBUG4, "external type: %s", type);
959-
populate_typ_array();
949+
populate_typ_list();
960950
return gettype(type);
961951
}
962952
elog(ERROR, "unrecognized type \"%s\"", type);
@@ -984,17 +974,20 @@ boot_get_type_io_data(Oid typid,
984974
Oid *typinput,
985975
Oid *typoutput)
986976
{
987-
if (Typ != NULL)
977+
if (Typ != NIL)
988978
{
989979
/* We have the boot-time contents of pg_type, so use it */
990-
struct typmap **app;
991-
struct typmap *ap;
992-
993-
app = Typ;
994-
while (*app && (*app)->am_oid != typid)
995-
++app;
996-
ap = *app;
997-
if (ap == NULL)
980+
struct typmap *ap = NULL;
981+
ListCell *lc;
982+
983+
foreach (lc, Typ)
984+
{
985+
ap = lfirst(lc);
986+
if (ap->am_oid == typid)
987+
break;
988+
}
989+
990+
if (!ap || ap->am_oid != typid)
998991
elog(ERROR, "type OID %u not found in Typ list", typid);
999992

1000993
*typlen = ap->am_typ.typlen;

0 commit comments

Comments
 (0)