mirror of
https://github.com/postgres/postgres.git
synced 2025-05-05 09:19:17 +03:00
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
This commit is contained in:
parent
5b861baa55
commit
e1a5e65703
@ -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
|
|||||||
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)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
|
|
||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* 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);
|
Assert(Typ == NIL);
|
||||||
|
|
||||||
nalloc = 512;
|
|
||||||
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)
|
|||||||
*
|
*
|
||||||
* 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)
|
|||||||
}
|
}
|
||||||
/* 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,
|
|||||||
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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user