88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.38 1999/09/18 19:07:06 tgl Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.39 1999/11/21 23:25:47 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
1515#include <math.h>
1616
1717#include "postgres.h"
18+
1819#include "access/genam.h"
1920#include "access/heapam.h"
2021#include "catalog/catname.h"
@@ -38,8 +39,8 @@ static void IndexSelectivity(Oid indexrelid, Oid baserelid, int nIndexKeys,
3839
3940/*
4041 * relation_info -
41- * Retrieves catalog information for a given relation. Given the oid of
42- * the relation, return the followinginformation :
42+ * Retrieves catalog information for a given relation.
43+ *Given therangetable index of the relation, return the followinginfo :
4344 *whether the relation has secondary indices
4445 *number of pages
4546 *number of tuples
@@ -54,166 +55,141 @@ relation_info(Query *root, Index relid,
5455
5556relationObjectId = getrelid (relid ,root -> rtable );
5657relationTuple = SearchSysCacheTuple (RELOID ,
57- ObjectIdGetDatum (relationObjectId ),
58+ ObjectIdGetDatum (relationObjectId ),
58590 ,0 ,0 );
5960if (HeapTupleIsValid (relationTuple ))
6061{
6162relation = (Form_pg_class )GETSTRUCT (relationTuple );
6263
63- * hasindex = (relation -> relhasindex ) ?TRUE :FALSE ;
64+ * hasindex = (relation -> relhasindex ) ?true :false ;
6465* pages = relation -> relpages ;
6566* tuples = relation -> reltuples ;
6667}
6768else
6869{
69- elog (ERROR ,"RelationCatalogInformation : Relation %u not found" ,
70+ elog (ERROR ,"relation_info : Relation %u not found" ,
7071relationObjectId );
7172}
72-
73- return ;
7473}
7574
76-
7775/*
78- * index_info
79- * Retrieves catalog information on an index on a given relation.
76+ * find_secondary_indexes
77+ * Creates a list of RelOptInfo nodes containing information for each
78+ * secondary index defined on the given relation.
8079 *
81- * The index relation is opened on the first invocation. The current
82- * retrieves the next index relation within the catalog that has not
83- * already been retrieved by a previous call. The index catalog
84- * is closed when no more indices for 'relid' can be found.
85- *
86- * 'first' is 1 if this is the first call
87- *
88- * Returns true if successful and false otherwise. Index info is returned
89- * via the transient data structure 'info'.
80+ * 'relid' is the RT index of the relation for which indices are being located
9081 *
82+ * Returns a list of new index RelOptInfo nodes.
9183 */
92- bool
93- index_info (Query * root ,bool first , int relid , IdxInfoRetval * info )
84+ List *
85+ find_secondary_indexes (Query * root ,Index relid )
9486{
95- int i ;
96- HeapTuple indexTuple ,
97- amopTuple ;
98- Form_pg_index index ;
99- Relation indexRelation ;
100- uint16 amstrategy ;
101- Oid relam ;
102- Oid indrelid ;
103-
104- static Relation relation = (Relation )NULL ;
105- static HeapScanDesc scan = (HeapScanDesc )NULL ;
106- static ScanKeyData indexKey ;
87+ List * indexes = NIL ;
88+ Oid indrelid = getrelid (relid ,root -> rtable );
89+ Relation relation ;
90+ HeapScanDesc scan ;
91+ ScanKeyData indexKey ;
92+ HeapTuple indexTuple ;
10793
94+ /* Scan pg_index for tuples describing indexes of this rel */
95+ relation = heap_openr (IndexRelationName ,AccessShareLock );
10896
109- /* find the oid of the indexed relation */
110- indrelid = getrelid (relid ,root -> rtable );
97+ ScanKeyEntryInitialize (& indexKey ,0 ,
98+ Anum_pg_index_indrelid ,
99+ F_OIDEQ ,
100+ ObjectIdGetDatum (indrelid ));
111101
112- MemSet (info ,0 ,sizeof (IdxInfoRetval ));
102+ scan = heap_beginscan (relation ,0 ,SnapshotNow ,
103+ 1 ,& indexKey );
113104
114- /*
115- * the maximum number of elements in each of the following arrays is
116- * 8. We allocate one more for a terminating 0 to indicate the end of
117- * the array.
118- */
119- info -> indexkeys = (int * )palloc (sizeof (int )* 9 );
120- MemSet (info -> indexkeys ,0 ,sizeof (int )* 9 );
121- info -> orderOprs = (Oid * )palloc (sizeof (Oid )* 9 );
122- MemSet (info -> orderOprs ,0 ,sizeof (Oid )* 9 );
123- info -> classlist = (Oid * )palloc (sizeof (Oid )* 9 );
124- MemSet (info -> classlist ,0 ,sizeof (Oid )* 9 );
125-
126- /* Find an index on the given relation */
127- if (first )
128- {
129- if (HeapScanIsValid (scan ))
130- heap_endscan (scan );
131- scan = (HeapScanDesc )NULL ;
132- if (RelationIsValid (relation ))
133- heap_close (relation ,AccessShareLock );
134- relation = (Relation )NULL ;
135-
136- ScanKeyEntryInitialize (& indexKey ,0 ,
137- Anum_pg_index_indrelid ,
138- F_OIDEQ ,
139- ObjectIdGetDatum (indrelid ));
140-
141- relation = heap_openr (IndexRelationName ,AccessShareLock );
142- scan = heap_beginscan (relation ,0 ,SnapshotNow ,
143- 1 ,& indexKey );
144- }
145- if (!HeapScanIsValid (scan ))
146- elog (ERROR ,"index_info: scan not started" );
147- indexTuple = heap_getnext (scan ,0 );
148- if (!HeapTupleIsValid (indexTuple ))
149- {
150- heap_endscan (scan );
151- heap_close (relation ,AccessShareLock );
152- scan = (HeapScanDesc )NULL ;
153- relation = (Relation )NULL ;
154- return 0 ;
155- }
156-
157- /* Extract info from the index tuple */
158- index = (Form_pg_index )GETSTRUCT (indexTuple );
159- info -> relid = index -> indexrelid ;/* index relation */
160- for (i = 0 ;i < INDEX_MAX_KEYS ;i ++ )
161- info -> indexkeys [i ]= index -> indkey [i ];
162- for (i = 0 ;i < INDEX_MAX_KEYS ;i ++ )
163- info -> classlist [i ]= index -> indclass [i ];
164-
165- info -> indproc = index -> indproc ;/* functional index ?? */
166-
167- /* partial index ?? */
168- if (VARSIZE (& index -> indpred )!= 0 )
105+ while (HeapTupleIsValid (indexTuple = heap_getnext (scan ,0 )))
169106{
107+ Form_pg_index index = (Form_pg_index )GETSTRUCT (indexTuple );
108+ RelOptInfo * info = makeNode (RelOptInfo );
109+ int i ;
110+ Relation indexRelation ;
111+ uint16 amstrategy ;
112+ Oid relam ;
170113
171114/*
172- * The memory allocated here for the predicate (in lispReadString)
173- * only needs to stay around until it's used in find_index_paths,
174- * which is all within a command, so the automatic pfree at end of
175- * transaction should be ok.
115+ * Need to make these arrays large enough to be sure there is a
116+ * terminating 0 at the end of each one.
176117 */
177- char * predString ;
118+ info -> classlist = (Oid * )palloc (sizeof (Oid )* (INDEX_MAX_KEYS + 1 ));
119+ info -> indexkeys = (int * )palloc (sizeof (int )* (INDEX_MAX_KEYS + 1 ));
120+ info -> ordering = (Oid * )palloc (sizeof (Oid )* (INDEX_MAX_KEYS + 1 ));
121+
122+ /* Extract info from the pg_index tuple */
123+ info -> relids = lconsi (index -> indexrelid ,NIL );
124+ info -> indproc = index -> indproc ;/* functional index ?? */
125+ if (VARSIZE (& index -> indpred )!= 0 )/* partial index ?? */
126+ {
127+ char * predString = fmgr (F_TEXTOUT ,& index -> indpred );
128+ info -> indpred = (List * )stringToNode (predString );
129+ pfree (predString );
130+ }
131+ else
132+ info -> indpred = NIL ;
178133
179- predString = fmgr (F_TEXTOUT ,& index -> indpred );
180- info -> indpred = (Node * )stringToNode (predString );
181- pfree (predString );
182- }
134+ for (i = 0 ;i < INDEX_MAX_KEYS ;i ++ )
135+ info -> indexkeys [i ]= index -> indkey [i ];
136+ info -> indexkeys [INDEX_MAX_KEYS ]= 0 ;
137+ for (i = 0 ;i < INDEX_MAX_KEYS ;i ++ )
138+ info -> classlist [i ]= index -> indclass [i ];
139+ info -> classlist [INDEX_MAX_KEYS ]= (Oid )0 ;
183140
184- /* Extract info from the relation descriptor for the index */
185- indexRelation = index_open (index -> indexrelid );
141+ /* Extract info from the relation descriptor for the index */
142+ indexRelation = index_open (index -> indexrelid );
186143#ifdef notdef
187- /* XXX should iterate through strategies -- but how? use #1 for now */
188- amstrategy = indexRelation -> rd_am -> amstrategies ;
144+ /* XXX should iterate through strategies -- but how? use #1 for now */
145+ amstrategy = indexRelation -> rd_am -> amstrategies ;
189146#endif /* notdef */
190- amstrategy = 1 ;
191- relam = indexRelation -> rd_rel -> relam ;
192- info -> relam = relam ;
193- info -> pages = indexRelation -> rd_rel -> relpages ;
194- info -> tuples = indexRelation -> rd_rel -> reltuples ;
195- index_close (indexRelation );
147+ amstrategy = 1 ;
148+ relam = indexRelation -> rd_rel -> relam ;
149+ info -> relam = relam ;
150+ info -> pages = indexRelation -> rd_rel -> relpages ;
151+ info -> tuples = indexRelation -> rd_rel -> reltuples ;
152+ index_close (indexRelation );
196153
197- /*
198- * Find the index ordering keys
199- *
200- * Must use indclass to know when to stop looking since with functional
201- * indices there could be several keys (args) for one opclass. -mer 27
202- * Sept 1991
203- */
204- for (i = 0 ;i < 8 && index -> indclass [i ];++ i )
205- {
206- amopTuple = SearchSysCacheTuple (AMOPSTRATEGY ,
154+ /*
155+ * Fetch the ordering operators associated with the index.
156+ *
157+ * XXX what if it's a hash or other unordered index?
158+ */
159+ MemSet (info -> ordering ,0 ,sizeof (Oid )* (INDEX_MAX_KEYS + 1 ));
160+ for (i = 0 ;i < INDEX_MAX_KEYS && index -> indclass [i ];i ++ )
161+ {
162+ HeapTuple amopTuple ;
163+
164+ amopTuple = SearchSysCacheTuple (AMOPSTRATEGY ,
207165ObjectIdGetDatum (relam ),
208- ObjectIdGetDatum (index -> indclass [i ]),
166+ ObjectIdGetDatum (index -> indclass [i ]),
209167UInt16GetDatum (amstrategy ),
2101680 );
211- if (!HeapTupleIsValid (amopTuple ))
212- elog (ERROR ,"index_info: no amop %u %u %d" ,
213- relam ,index -> indclass [i ],amstrategy );
214- info -> orderOprs [i ]= ((Form_pg_amop )GETSTRUCT (amopTuple ))-> amopopr ;
169+ if (!HeapTupleIsValid (amopTuple ))
170+ elog (ERROR ,"find_secondary_indexes: no amop %u %u %d" ,
171+ relam ,index -> indclass [i ],amstrategy );
172+ info -> ordering [i ]= ((Form_pg_amop )GETSTRUCT (amopTuple ))-> amopopr ;
173+ }
174+
175+ info -> indexed = false;/* not indexed itself */
176+ info -> size = 0 ;
177+ info -> width = 0 ;
178+ info -> targetlist = NIL ;
179+ info -> pathlist = NIL ;
180+ info -> cheapestpath = NULL ;
181+ info -> pruneable = true;
182+ info -> restrictinfo = NIL ;
183+ info -> joininfo = NIL ;
184+ info -> innerjoin = NIL ;
185+
186+ indexes = lcons (info ,indexes );
215187}
216- return TRUE;
188+
189+ heap_endscan (scan );
190+ heap_close (relation ,AccessShareLock );
191+
192+ return indexes ;
217193}
218194
219195/*
@@ -370,10 +346,10 @@ join_selectivity(Oid functionObjectId,
370346}
371347
372348/*
373- *find_all_inheritors
349+ *find_inheritance_children
374350 *
375- * Returnsa LISP list containing the OIDs of all relations which
376- *inherits from the relation with OID 'inhparent'.
351+ * Returnsan integer list containing the OIDs of all relations which
352+ *inherit *directly* from the relation with OID 'inhparent'.
377353 */
378354List *
379355find_inheritance_children (Oid inhparent )
@@ -390,8 +366,8 @@ find_inheritance_children(Oid inhparent)
390366
391367fmgr_info (F_OIDEQ ,& key [0 ].sk_func );
392368key [0 ].sk_nargs = key [0 ].sk_func .fn_nargs ;
369+ key [0 ].sk_argument = ObjectIdGetDatum (inhparent );
393370
394- key [0 ].sk_argument = ObjectIdGetDatum ((Oid )inhparent );
395371relation = heap_openr (InheritsRelationName ,AccessShareLock );
396372scan = heap_beginscan (relation ,0 ,SnapshotNow ,1 ,key );
397373while (HeapTupleIsValid (inheritsTuple = heap_getnext (scan ,0 )))