8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
15
15
#include <math.h>
16
16
17
17
#include "postgres.h"
18
+
18
19
#include "access/genam.h"
19
20
#include "access/heapam.h"
20
21
#include "catalog/catname.h"
@@ -38,8 +39,8 @@ static void IndexSelectivity(Oid indexrelid, Oid baserelid, int nIndexKeys,
38
39
39
40
/*
40
41
* relation_info -
41
- * Retrieves catalog information for a given relation. Given the oid of
42
- * the relation, return the following information :
42
+ * Retrieves catalog information for a given relation.
43
+ * Given the rangetable index of the relation, return the following info :
43
44
* whether the relation has secondary indices
44
45
* number of pages
45
46
* number of tuples
@@ -54,166 +55,141 @@ relation_info(Query *root, Index relid,
54
55
55
56
relationObjectId = getrelid (relid , root -> rtable );
56
57
relationTuple = SearchSysCacheTuple (RELOID ,
57
- ObjectIdGetDatum (relationObjectId ),
58
+ ObjectIdGetDatum (relationObjectId ),
58
59
0 , 0 , 0 );
59
60
if (HeapTupleIsValid (relationTuple ))
60
61
{
61
62
relation = (Form_pg_class ) GETSTRUCT (relationTuple );
62
63
63
- * hasindex = (relation -> relhasindex ) ? TRUE : FALSE ;
64
+ * hasindex = (relation -> relhasindex ) ? true : false ;
64
65
* pages = relation -> relpages ;
65
66
* tuples = relation -> reltuples ;
66
67
}
67
68
else
68
69
{
69
- elog (ERROR , "RelationCatalogInformation : Relation %u not found" ,
70
+ elog (ERROR , "relation_info : Relation %u not found" ,
70
71
relationObjectId );
71
72
}
72
-
73
- return ;
74
73
}
75
74
76
-
77
75
/*
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.
80
79
*
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
90
81
*
82
+ * Returns a list of new index RelOptInfo nodes.
91
83
*/
92
- bool
93
- index_info (Query * root , bool first , int relid , IdxInfoRetval * info )
84
+ List *
85
+ find_secondary_indexes (Query * root , Index relid )
94
86
{
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 ;
107
93
94
+ /* Scan pg_index for tuples describing indexes of this rel */
95
+ relation = heap_openr (IndexRelationName , AccessShareLock );
108
96
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 ));
111
101
112
- MemSet (info , 0 , sizeof (IdxInfoRetval ));
102
+ scan = heap_beginscan (relation , 0 , SnapshotNow ,
103
+ 1 , & indexKey );
113
104
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 )))
169
106
{
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 ;
170
113
171
114
/*
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.
176
117
*/
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 ;
178
133
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 ;
183
140
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 );
186
143
#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 ;
189
146
#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 );
196
153
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 ,
207
165
ObjectIdGetDatum (relam ),
208
- ObjectIdGetDatum (index -> indclass [i ]),
166
+ ObjectIdGetDatum (index -> indclass [i ]),
209
167
UInt16GetDatum (amstrategy ),
210
168
0 );
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 );
215
187
}
216
- return TRUE;
188
+
189
+ heap_endscan (scan );
190
+ heap_close (relation , AccessShareLock );
191
+
192
+ return indexes ;
217
193
}
218
194
219
195
/*
@@ -370,10 +346,10 @@ join_selectivity(Oid functionObjectId,
370
346
}
371
347
372
348
/*
373
- * find_all_inheritors
349
+ * find_inheritance_children
374
350
*
375
- * Returns a LISP list containing the OIDs of all relations which
376
- * inherits from the relation with OID 'inhparent'.
351
+ * Returns an integer list containing the OIDs of all relations which
352
+ * inherit *directly* from the relation with OID 'inhparent'.
377
353
*/
378
354
List *
379
355
find_inheritance_children (Oid inhparent )
@@ -390,8 +366,8 @@ find_inheritance_children(Oid inhparent)
390
366
391
367
fmgr_info (F_OIDEQ , & key [0 ].sk_func );
392
368
key [0 ].sk_nargs = key [0 ].sk_func .fn_nargs ;
369
+ key [0 ].sk_argument = ObjectIdGetDatum (inhparent );
393
370
394
- key [0 ].sk_argument = ObjectIdGetDatum ((Oid ) inhparent );
395
371
relation = heap_openr (InheritsRelationName , AccessShareLock );
396
372
scan = heap_beginscan (relation , 0 , SnapshotNow , 1 , key );
397
373
while (HeapTupleIsValid (inheritsTuple = heap_getnext (scan , 0 )))
0 commit comments