From 04fa5ca5449c1efcd484b3a6ec891b299513cdfd Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 7 Dec 1999 04:09:39 +0000 Subject: [PATCH] Clean up memory leakage in find_inheritors() by using pg_list lists (which are palloc'd) instead of DLLists (which are malloc'd). Not very significant, since this routine seldom has anything useful to do, but a leak is a leak... --- src/backend/parser/parse_func.c | 107 +++++++++++++------------------- 1 file changed, 44 insertions(+), 63 deletions(-) diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c index 8949ae3140..aafa4e4c9c 100644 --- a/src/backend/parser/parse_func.c +++ b/src/backend/parser/parse_func.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.62 1999/11/22 17:56:21 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.63 1999/12/07 04:09:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -21,9 +21,9 @@ #include "catalog/pg_aggregate.h" #include "catalog/pg_inherits.h" #include "catalog/pg_proc.h" -#include "lib/dllist.h" #include "miscadmin.h" #include "nodes/makefuncs.h" +#include "nodes/pg_list.h" #include "nodes/relation.h" #include "parser/parse_agg.h" #include "parser/parse_coerce.h" @@ -70,11 +70,6 @@ static Oid agg_select_candidate(Oid typeid, CandidateList candidates); #define ISCOMPLEX(type) (typeidTypeRelid(type) ? true : false) -typedef struct _SuperQE -{ - Oid sqe_relid; -} SuperQE; - /* ** ParseNestedFuncOrColumn ** Given a nested dot expression (i.e. (relation func ... attr), build up @@ -1078,39 +1073,34 @@ argtype_inherit(int nargs, Oid *oid_array) static int find_inheritors(Oid relid, Oid **supervec) { - Oid *relidvec; Relation inhrel; HeapScanDesc inhscan; ScanKeyData skey; HeapTuple inhtup; - TupleDesc inhtupdesc; + Oid *relidvec; int nvisited; - SuperQE *qentry, - *vnode; - Dllist *visited, + List *visited, *queue; - Dlelem *qe, - *elt; - - Relation rd; - Datum d; + List *elt; bool newrelid; - char isNull; nvisited = 0; - queue = DLNewList(); - visited = DLNewList(); - + queue = NIL; + visited = NIL; inhrel = heap_openr(InheritsRelationName, AccessShareLock); - inhtupdesc = RelationGetDescr(inhrel); /* * Use queue to do a breadth-first traversal of the inheritance graph - * from the relid supplied up to the root. + * from the relid supplied up to the root. At the top of the loop, + * relid is the OID of the reltype to check next, queue is the list + * of pending rels to check after this one, and visited is the list + * of relids we need to output. */ do { + /* find all types this relid inherits from, and add them to queue */ + ScanKeyEntryInitialize(&skey, 0x0, Anum_pg_inherits_inhrelid, F_OIDEQ, ObjectIdGetDatum(relid)); @@ -1119,55 +1109,33 @@ find_inheritors(Oid relid, Oid **supervec) while (HeapTupleIsValid(inhtup = heap_getnext(inhscan, 0))) { - qentry = (SuperQE *) palloc(sizeof(SuperQE)); + Form_pg_inherits inh = (Form_pg_inherits) GETSTRUCT(inhtup); - d = fastgetattr(inhtup, Anum_pg_inherits_inhparent, - inhtupdesc, &isNull); - qentry->sqe_relid = DatumGetObjectId(d); - - /* put this one on the queue */ - DLAddTail(queue, DLNewElem(qentry)); + queue = lappendi(queue, inh->inhparent); } heap_endscan(inhscan); /* pull next unvisited relid off the queue */ - do + + newrelid = false; + while (queue != NIL) { - qe = DLRemHead(queue); - qentry = qe ? (SuperQE *) DLE_VAL(qe) : NULL; - - if (qentry == (SuperQE *) NULL) - break; - - relid = qentry->sqe_relid; - newrelid = true; - - for (elt = DLGetHead(visited); elt; elt = DLGetSucc(elt)) + relid = lfirsti(queue); + queue = lnext(queue); + if (! intMember(relid, visited)) { - vnode = (SuperQE *) DLE_VAL(elt); - if (vnode && (qentry->sqe_relid == vnode->sqe_relid)) - { - newrelid = false; - break; - } + newrelid = true; + break; } - } while (!newrelid); + } - if (qentry != (SuperQE *) NULL) + if (newrelid) { - /* save the type id, rather than the relation id */ - rd = heap_open(qentry->sqe_relid, NoLock); - if (! RelationIsValid(rd)) - elog(ERROR, "Relid %u does not exist", qentry->sqe_relid); - qentry->sqe_relid = typeTypeId(typenameType(RelationGetRelationName(rd))); - heap_close(rd, NoLock); - - DLAddTail(visited, qe); - + visited = lappendi(visited, relid); nvisited++; } - } while (qentry != (SuperQE *) NULL); + } while (newrelid); heap_close(inhrel, AccessShareLock); @@ -1176,16 +1144,29 @@ find_inheritors(Oid relid, Oid **supervec) relidvec = (Oid *) palloc(nvisited * sizeof(Oid)); *supervec = relidvec; - for (elt = DLGetHead(visited); elt; elt = DLGetSucc(elt)) + foreach(elt, visited) { - vnode = (SuperQE *) DLE_VAL(elt); - *relidvec++ = vnode->sqe_relid; - } + /* return the type id, rather than the relation id */ + Relation rd; + Oid trelid; + relid = lfirsti(elt); + rd = heap_open(relid, NoLock); + if (! RelationIsValid(rd)) + elog(ERROR, "Relid %u does not exist", relid); + trelid = typeTypeId(typenameType(RelationGetRelationName(rd))); + heap_close(rd, NoLock); + *relidvec++ = trelid; + } } else *supervec = (Oid *) NULL; + freeList(visited); + /* there doesn't seem to be any equally easy way to release the queue + * list cells, but since they're palloc'd space it's not critical. + */ + return nvisited; }