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...
This commit is contained in:
Tom Lane 1999-12-07 04:09:39 +00:00
parent 5ad4034a4c
commit 04fa5ca544

View File

@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * 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_aggregate.h"
#include "catalog/pg_inherits.h" #include "catalog/pg_inherits.h"
#include "catalog/pg_proc.h" #include "catalog/pg_proc.h"
#include "lib/dllist.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "nodes/makefuncs.h" #include "nodes/makefuncs.h"
#include "nodes/pg_list.h"
#include "nodes/relation.h" #include "nodes/relation.h"
#include "parser/parse_agg.h" #include "parser/parse_agg.h"
#include "parser/parse_coerce.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) #define ISCOMPLEX(type) (typeidTypeRelid(type) ? true : false)
typedef struct _SuperQE
{
Oid sqe_relid;
} SuperQE;
/* /*
** ParseNestedFuncOrColumn ** ParseNestedFuncOrColumn
** Given a nested dot expression (i.e. (relation func ... attr), build up ** 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 static int
find_inheritors(Oid relid, Oid **supervec) find_inheritors(Oid relid, Oid **supervec)
{ {
Oid *relidvec;
Relation inhrel; Relation inhrel;
HeapScanDesc inhscan; HeapScanDesc inhscan;
ScanKeyData skey; ScanKeyData skey;
HeapTuple inhtup; HeapTuple inhtup;
TupleDesc inhtupdesc; Oid *relidvec;
int nvisited; int nvisited;
SuperQE *qentry, List *visited,
*vnode;
Dllist *visited,
*queue; *queue;
Dlelem *qe, List *elt;
*elt;
Relation rd;
Datum d;
bool newrelid; bool newrelid;
char isNull;
nvisited = 0; nvisited = 0;
queue = DLNewList(); queue = NIL;
visited = DLNewList(); visited = NIL;
inhrel = heap_openr(InheritsRelationName, AccessShareLock); inhrel = heap_openr(InheritsRelationName, AccessShareLock);
inhtupdesc = RelationGetDescr(inhrel);
/* /*
* Use queue to do a breadth-first traversal of the inheritance graph * 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 do
{ {
/* find all types this relid inherits from, and add them to queue */
ScanKeyEntryInitialize(&skey, 0x0, Anum_pg_inherits_inhrelid, ScanKeyEntryInitialize(&skey, 0x0, Anum_pg_inherits_inhrelid,
F_OIDEQ, F_OIDEQ,
ObjectIdGetDatum(relid)); ObjectIdGetDatum(relid));
@ -1119,55 +1109,33 @@ find_inheritors(Oid relid, Oid **supervec)
while (HeapTupleIsValid(inhtup = heap_getnext(inhscan, 0))) 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, queue = lappendi(queue, inh->inhparent);
inhtupdesc, &isNull);
qentry->sqe_relid = DatumGetObjectId(d);
/* put this one on the queue */
DLAddTail(queue, DLNewElem(qentry));
} }
heap_endscan(inhscan); heap_endscan(inhscan);
/* pull next unvisited relid off the queue */ /* pull next unvisited relid off the queue */
do
newrelid = false;
while (queue != NIL)
{ {
qe = DLRemHead(queue); relid = lfirsti(queue);
qentry = qe ? (SuperQE *) DLE_VAL(qe) : NULL; queue = lnext(queue);
if (! intMember(relid, visited))
if (qentry == (SuperQE *) NULL)
break;
relid = qentry->sqe_relid;
newrelid = true;
for (elt = DLGetHead(visited); elt; elt = DLGetSucc(elt))
{ {
vnode = (SuperQE *) DLE_VAL(elt); newrelid = true;
if (vnode && (qentry->sqe_relid == vnode->sqe_relid)) break;
{
newrelid = false;
break;
}
} }
} while (!newrelid); }
if (qentry != (SuperQE *) NULL) if (newrelid)
{ {
/* save the type id, rather than the relation id */ visited = lappendi(visited, relid);
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);
nvisited++; nvisited++;
} }
} while (qentry != (SuperQE *) NULL); } while (newrelid);
heap_close(inhrel, AccessShareLock); heap_close(inhrel, AccessShareLock);
@ -1176,16 +1144,29 @@ find_inheritors(Oid relid, Oid **supervec)
relidvec = (Oid *) palloc(nvisited * sizeof(Oid)); relidvec = (Oid *) palloc(nvisited * sizeof(Oid));
*supervec = relidvec; *supervec = relidvec;
for (elt = DLGetHead(visited); elt; elt = DLGetSucc(elt)) foreach(elt, visited)
{ {
vnode = (SuperQE *) DLE_VAL(elt); /* return the type id, rather than the relation id */
*relidvec++ = vnode->sqe_relid; 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 else
*supervec = (Oid *) NULL; *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; return nvisited;
} }