mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-06 15:24:56 +08:00
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:
parent
5ad4034a4c
commit
04fa5ca544
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user