77 *
88 *
99 * IDENTIFICATION
10- * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.62 1999/11/22 17:56:21 momjian Exp $
10+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.63 1999/12/07 04:09:39 tgl Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
2121#include "catalog/pg_aggregate.h"
2222#include "catalog/pg_inherits.h"
2323#include "catalog/pg_proc.h"
24- #include "lib/dllist.h"
2524#include "miscadmin.h"
2625#include "nodes/makefuncs.h"
26+ #include "nodes/pg_list.h"
2727#include "nodes/relation.h"
2828#include "parser/parse_agg.h"
2929#include "parser/parse_coerce.h"
@@ -70,11 +70,6 @@ static Oidagg_select_candidate(Oid typeid, CandidateList candidates);
7070
7171#define ISCOMPLEX (type ) (typeidTypeRelid(type) ? true : false)
7272
73- typedef struct _SuperQE
74- {
75- Oid sqe_relid ;
76- }SuperQE ;
77-
7873/*
7974 ** ParseNestedFuncOrColumn
8075 ** Given a nested dot expression (i.e. (relation func ... attr), build up
@@ -1078,39 +1073,34 @@ argtype_inherit(int nargs, Oid *oid_array)
10781073static int
10791074find_inheritors (Oid relid ,Oid * * supervec )
10801075{
1081- Oid * relidvec ;
10821076Relation inhrel ;
10831077HeapScanDesc inhscan ;
10841078ScanKeyData skey ;
10851079HeapTuple inhtup ;
1086- TupleDesc inhtupdesc ;
1080+ Oid * relidvec ;
10871081int nvisited ;
1088- SuperQE * qentry ,
1089- * vnode ;
1090- Dllist * visited ,
1082+ List * visited ,
10911083* queue ;
1092- Dlelem * qe ,
1093- * elt ;
1094-
1095- Relation rd ;
1096- Datum d ;
1084+ List * elt ;
10971085bool newrelid ;
1098- char isNull ;
10991086
11001087nvisited = 0 ;
1101- queue = DLNewList ();
1102- visited = DLNewList ();
1103-
1088+ queue = NIL ;
1089+ visited = NIL ;
11041090
11051091inhrel = heap_openr (InheritsRelationName ,AccessShareLock );
1106- inhtupdesc = RelationGetDescr (inhrel );
11071092
11081093/*
11091094 * Use queue to do a breadth-first traversal of the inheritance graph
1110- * from the relid supplied up to the root.
1095+ * from the relid supplied up to the root. At the top of the loop,
1096+ * relid is the OID of the reltype to check next, queue is the list
1097+ * of pending rels to check after this one, and visited is the list
1098+ * of relids we need to output.
11111099 */
11121100do
11131101{
1102+ /* find all types this relid inherits from, and add them to queue */
1103+
11141104ScanKeyEntryInitialize (& skey ,0x0 ,Anum_pg_inherits_inhrelid ,
11151105F_OIDEQ ,
11161106ObjectIdGetDatum (relid ));
@@ -1119,55 +1109,33 @@ find_inheritors(Oid relid, Oid **supervec)
11191109
11201110while (HeapTupleIsValid (inhtup = heap_getnext (inhscan ,0 )))
11211111{
1122- qentry = (SuperQE * ) palloc ( sizeof ( SuperQE ) );
1112+ Form_pg_inherits inh = (Form_pg_inherits ) GETSTRUCT ( inhtup );
11231113
1124- d = fastgetattr (inhtup ,Anum_pg_inherits_inhparent ,
1125- inhtupdesc ,& isNull );
1126- qentry -> sqe_relid = DatumGetObjectId (d );
1127-
1128- /* put this one on the queue */
1129- DLAddTail (queue ,DLNewElem (qentry ));
1114+ queue = lappendi (queue ,inh -> inhparent );
11301115}
11311116
11321117heap_endscan (inhscan );
11331118
11341119/* pull next unvisited relid off the queue */
1135- do
1136- {
1137- qe = DLRemHead (queue );
1138- qentry = qe ? (SuperQE * )DLE_VAL (qe ) :NULL ;
1139-
1140- if (qentry == (SuperQE * )NULL )
1141- break ;
11421120
1143- relid = qentry -> sqe_relid ;
1144- newrelid = true;
1145-
1146- for (elt = DLGetHead (visited );elt ;elt = DLGetSucc (elt ))
1121+ newrelid = false;
1122+ while (queue != NIL )
1123+ {
1124+ relid = lfirsti (queue );
1125+ queue = lnext (queue );
1126+ if (!intMember (relid ,visited ))
11471127{
1148- vnode = (SuperQE * )DLE_VAL (elt );
1149- if (vnode && (qentry -> sqe_relid == vnode -> sqe_relid ))
1150- {
1151- newrelid = false;
1152- break ;
1153- }
1128+ newrelid = true;
1129+ break ;
11541130}
1155- }while (! newrelid );
1131+ }
11561132
1157- if (qentry != ( SuperQE * ) NULL )
1133+ if (newrelid )
11581134{
1159- /* save the type id, rather than the relation id */
1160- rd = heap_open (qentry -> sqe_relid ,NoLock );
1161- if (!RelationIsValid (rd ))
1162- elog (ERROR ,"Relid %u does not exist" ,qentry -> sqe_relid );
1163- qentry -> sqe_relid = typeTypeId (typenameType (RelationGetRelationName (rd )));
1164- heap_close (rd ,NoLock );
1165-
1166- DLAddTail (visited ,qe );
1167-
1135+ visited = lappendi (visited ,relid );
11681136nvisited ++ ;
11691137}
1170- }while (qentry != ( SuperQE * ) NULL );
1138+ }while (newrelid );
11711139
11721140heap_close (inhrel ,AccessShareLock );
11731141
@@ -1176,16 +1144,29 @@ find_inheritors(Oid relid, Oid **supervec)
11761144relidvec = (Oid * )palloc (nvisited * sizeof (Oid ));
11771145* supervec = relidvec ;
11781146
1179- for (elt = DLGetHead ( visited ); elt ; elt = DLGetSucc ( elt ) )
1147+ foreach (elt , visited )
11801148{
1181- vnode = ( SuperQE * ) DLE_VAL ( elt );
1182- * relidvec ++ = vnode -> sqe_relid ;
1183- }
1149+ /* return the type id, rather than the relation id */
1150+ Relation rd ;
1151+ Oid trelid ;
11841152
1153+ relid = lfirsti (elt );
1154+ rd = heap_open (relid ,NoLock );
1155+ if (!RelationIsValid (rd ))
1156+ elog (ERROR ,"Relid %u does not exist" ,relid );
1157+ trelid = typeTypeId (typenameType (RelationGetRelationName (rd )));
1158+ heap_close (rd ,NoLock );
1159+ * relidvec ++ = trelid ;
1160+ }
11851161}
11861162else
11871163* supervec = (Oid * )NULL ;
11881164
1165+ freeList (visited );
1166+ /* there doesn't seem to be any equally easy way to release the queue
1167+ * list cells, but since they're palloc'd space it's not critical.
1168+ */
1169+
11891170return nvisited ;
11901171}
11911172