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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy