Clean up memory leakage in find_inheritors() by using pg_list lists
authorTom Lane
Tue, 7 Dec 1999 04:09:39 +0000 (04:09 +0000)
committerTom Lane
Tue, 7 Dec 1999 04:09:39 +0000 (04:09 +0000)
(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

index 8949ae314043c9faa8d50247ba752229c29ff1b0..aafa4e4c9cb057a25113e61b34fa1f2a3b05656b 100644 (file)
@@ -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
-       {
-           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))
+       newrelid = false;
+       while (queue != NIL)
+       {
+           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;
 }