Commit e1a5e657 authored by Tomas Vondra's avatar Tomas Vondra

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
parent 5b861baa
...@@ -59,7 +59,7 @@ static void BootstrapModeMain(void); ...@@ -59,7 +59,7 @@ static void BootstrapModeMain(void);
static void bootstrap_signals(void); static void bootstrap_signals(void);
static void ShutdownAuxiliaryProcess(int code, Datum arg); static void ShutdownAuxiliaryProcess(int code, Datum arg);
static Form_pg_attribute AllocateAttribute(void); static Form_pg_attribute AllocateAttribute(void);
static void populate_typ_array(void); static void populate_typ_list(void);
static Oid gettype(char *type); static Oid gettype(char *type);
static void cleanup(void); static void cleanup(void);
...@@ -160,7 +160,7 @@ struct typmap ...@@ -160,7 +160,7 @@ struct typmap
FormData_pg_type am_typ; FormData_pg_type am_typ;
}; };
static struct typmap **Typ = NULL; static List *Typ = NIL; /* List of struct typmap* */
static struct typmap *Ap = NULL; static struct typmap *Ap = NULL;
static Datum values[MAXATTR]; /* current row's attribute values */ static Datum values[MAXATTR]; /* current row's attribute values */
...@@ -598,10 +598,10 @@ boot_openrel(char *relname) ...@@ -598,10 +598,10 @@ boot_openrel(char *relname)
/* /*
* pg_type must be filled before any OPEN command is executed, hence we * pg_type must be filled before any OPEN command is executed, hence we
* can now populate the Typ array if we haven't yet. * can now populate Typ if we haven't yet.
*/ */
if (Typ == NULL) if (Typ == NIL)
populate_typ_array(); populate_typ_list();
if (boot_reldesc != NULL) if (boot_reldesc != NULL)
closerel(NULL); closerel(NULL);
...@@ -691,7 +691,7 @@ DefineAttr(char *name, char *type, int attnum, int nullness) ...@@ -691,7 +691,7 @@ DefineAttr(char *name, char *type, int attnum, int nullness)
typeoid = gettype(type); typeoid = gettype(type);
if (Typ != NULL) if (Typ != NIL)
{ {
attrtypes[attnum]->atttypid = Ap->am_oid; attrtypes[attnum]->atttypid = Ap->am_oid;
attrtypes[attnum]->attlen = Ap->am_typ.typlen; attrtypes[attnum]->attlen = Ap->am_typ.typlen;
...@@ -873,47 +873,36 @@ cleanup(void) ...@@ -873,47 +873,36 @@ cleanup(void)
} }
/* ---------------- /* ----------------
* populate_typ_array * populate_typ_list
* *
* Load the Typ array by reading pg_type. * Load the Typ list by reading pg_type.
* ---------------- * ----------------
*/ */
static void static void
populate_typ_array(void) populate_typ_list(void)
{ {
Relation rel; Relation rel;
TableScanDesc scan; TableScanDesc scan;
HeapTuple tup; HeapTuple tup;
int nalloc; MemoryContext old;
int i;
Assert(Typ == NULL);
nalloc = 512; Assert(Typ == NIL);
Typ = (struct typmap **)
MemoryContextAlloc(TopMemoryContext, nalloc * sizeof(struct typmap *));
rel = table_open(TypeRelationId, NoLock); rel = table_open(TypeRelationId, NoLock);
scan = table_beginscan_catalog(rel, 0, NULL); scan = table_beginscan_catalog(rel, 0, NULL);
i = 0; old = MemoryContextSwitchTo(TopMemoryContext);
while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL) while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
{ {
Form_pg_type typForm = (Form_pg_type) GETSTRUCT(tup); Form_pg_type typForm = (Form_pg_type) GETSTRUCT(tup);
struct typmap *newtyp;
/* make sure there will be room for a trailing NULL pointer */ newtyp = (struct typmap *) palloc(sizeof(struct typmap));
if (i >= nalloc - 1) Typ = lappend(Typ, newtyp);
{
nalloc *= 2; newtyp->am_oid = typForm->oid;
Typ = (struct typmap **) memcpy(&newtyp->am_typ, typForm, sizeof(newtyp->am_typ));
repalloc(Typ, nalloc * sizeof(struct typmap *));
}
Typ[i] = (struct typmap *)
MemoryContextAlloc(TopMemoryContext, sizeof(struct typmap));
Typ[i]->am_oid = typForm->oid;
memcpy(&(Typ[i]->am_typ), typForm, sizeof(Typ[i]->am_typ));
i++;
} }
Typ[i] = NULL; /* Fill trailing NULL pointer */ MemoryContextSwitchTo(old);
table_endscan(scan); table_endscan(scan);
table_close(rel, NoLock); table_close(rel, NoLock);
} }
...@@ -923,25 +912,26 @@ populate_typ_array(void) ...@@ -923,25 +912,26 @@ populate_typ_array(void)
* *
* NB: this is really ugly; it will return an integer index into TypInfo[], * NB: this is really ugly; it will return an integer index into TypInfo[],
* and not an OID at all, until the first reference to a type not known in * and not an OID at all, until the first reference to a type not known in
* TypInfo[]. At that point it will read and cache pg_type in the Typ array, * TypInfo[]. At that point it will read and cache pg_type in Typ,
* and subsequently return a real OID (and set the global pointer Ap to * and subsequently return a real OID (and set the global pointer Ap to
* point at the found row in Typ). So caller must check whether Typ is * point at the found row in Typ). So caller must check whether Typ is
* still NULL to determine what the return value is! * still NIL to determine what the return value is!
* ---------------- * ----------------
*/ */
static Oid static Oid
gettype(char *type) gettype(char *type)
{ {
if (Typ != NULL) if (Typ != NIL)
{ {
struct typmap **app; ListCell *lc;
for (app = Typ; *app != NULL; app++) foreach (lc, Typ)
{ {
if (strncmp(NameStr((*app)->am_typ.typname), type, NAMEDATALEN) == 0) struct typmap *app = lfirst(lc);
if (strncmp(NameStr(app->am_typ.typname), type, NAMEDATALEN) == 0)
{ {
Ap = *app; Ap = app;
return (*app)->am_oid; return app->am_oid;
} }
} }
} }
...@@ -956,7 +946,7 @@ gettype(char *type) ...@@ -956,7 +946,7 @@ gettype(char *type)
} }
/* Not in TypInfo, so we'd better be able to read pg_type now */ /* Not in TypInfo, so we'd better be able to read pg_type now */
elog(DEBUG4, "external type: %s", type); elog(DEBUG4, "external type: %s", type);
populate_typ_array(); populate_typ_list();
return gettype(type); return gettype(type);
} }
elog(ERROR, "unrecognized type \"%s\"", type); elog(ERROR, "unrecognized type \"%s\"", type);
...@@ -984,17 +974,20 @@ boot_get_type_io_data(Oid typid, ...@@ -984,17 +974,20 @@ boot_get_type_io_data(Oid typid,
Oid *typinput, Oid *typinput,
Oid *typoutput) Oid *typoutput)
{ {
if (Typ != NULL) if (Typ != NIL)
{ {
/* We have the boot-time contents of pg_type, so use it */ /* We have the boot-time contents of pg_type, so use it */
struct typmap **app; struct typmap *ap = NULL;
struct typmap *ap; ListCell *lc;
app = Typ; foreach (lc, Typ)
while (*app && (*app)->am_oid != typid) {
++app; ap = lfirst(lc);
ap = *app; if (ap->am_oid == typid)
if (ap == NULL) break;
}
if (!ap || ap->am_oid != typid)
elog(ERROR, "type OID %u not found in Typ list", typid); elog(ERROR, "type OID %u not found in Typ list", typid);
*typlen = ap->am_typ.typlen; *typlen = ap->am_typ.typlen;
......
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