Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 610dfa6

Browse files
committed
Combine index_info and find_secondary_indexes into a single routine that
returns a list of RelOptInfos, eliminating the need for static state in index_info. That static state was a direct cause of coredumps; if anything decided to elog(ERROR) partway through an index_info search of pg_index, the next query would try to close a scan pointer that was pointing at no-longer-valid memory. Another example of the reasons to avoid static state variables...
1 parent 40d3e92 commit 610dfa6

File tree

3 files changed

+115
-214
lines changed

3 files changed

+115
-214
lines changed

src/backend/optimizer/util/indexnode.c

Lines changed: 2 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,16 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/indexnode.c,v 1.20 1999/08/16 02:17:57 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/indexnode.c,v 1.21 1999/11/21 23:25:47 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
14-
#include <sys/types.h>
15-
1614
#include "postgres.h"
1715

18-
1916
#include "optimizer/pathnode.h"
2017
#include "optimizer/plancat.h"
2118

2219

23-
static List *find_secondary_index(Query *root, Oid relid);
24-
2520
/*
2621
* find_relation_indices
2722
* Returns a list of index nodes containing appropriate information for
@@ -32,56 +27,7 @@ List *
3227
find_relation_indices(Query *root, RelOptInfo *rel)
3328
{
3429
if (rel->indexed)
35-
return find_secondary_index(root, lfirsti(rel->relids));
30+
return find_secondary_indexes(root, lfirsti(rel->relids));
3631
else
3732
return NIL;
3833
}
39-
40-
/*
41-
* find_secondary_index
42-
* Creates a list of RelOptInfo nodes containing information for each
43-
* secondary index defined on a relation by searching through the index
44-
* catalog.
45-
*
46-
* 'relid' is the OID of the relation for which indices are being located
47-
*
48-
* Returns a list of new index RelOptInfo nodes.
49-
*/
50-
static List *
51-
find_secondary_index(Query *root, Oid relid)
52-
{
53-
IdxInfoRetval indexinfo;
54-
List *indexes = NIL;
55-
bool first = true;
56-
57-
while (index_info(root, first, relid, &indexinfo))
58-
{
59-
RelOptInfo *indexnode = makeNode(RelOptInfo);
60-
61-
indexnode->relids = lconsi(indexinfo.relid, NIL);
62-
indexnode->relam = indexinfo.relam;
63-
indexnode->pages = indexinfo.pages;
64-
indexnode->tuples = indexinfo.tuples;
65-
indexnode->classlist = indexinfo.classlist;
66-
indexnode->indexkeys = indexinfo.indexkeys;
67-
indexnode->ordering = indexinfo.orderOprs;
68-
indexnode->indproc = indexinfo.indproc;
69-
indexnode->indpred = (List *) indexinfo.indpred;
70-
71-
indexnode->indexed = false; /* not indexed itself */
72-
indexnode->size = 0;
73-
indexnode->width = 0;
74-
indexnode->targetlist = NIL;
75-
indexnode->pathlist = NIL;
76-
indexnode->cheapestpath = NULL;
77-
indexnode->pruneable = true;
78-
indexnode->restrictinfo = NIL;
79-
indexnode->joininfo = NIL;
80-
indexnode->innerjoin = NIL;
81-
82-
indexes = lcons(indexnode, indexes);
83-
first = false;
84-
}
85-
86-
return indexes;
87-
}

src/backend/optimizer/util/plancat.c

Lines changed: 107 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@
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 following information:
42+
* Retrieves catalog information for a given relation.
43+
* Given the rangetable index of the relation, return the following info:
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

5556
relationObjectId = getrelid(relid, root->rtable);
5657
relationTuple = SearchSysCacheTuple(RELOID,
57-
ObjectIdGetDatum(relationObjectId),
58+
ObjectIdGetDatum(relationObjectId),
5859
0, 0, 0);
5960
if (HeapTupleIsValid(relationTuple))
6061
{
6162
relation = (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
}
6768
else
6869
{
69-
elog(ERROR, "RelationCatalogInformation: Relation %u not found",
70+
elog(ERROR, "relation_info: Relation %u not found",
7071
relationObjectId);
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,
207165
ObjectIdGetDatum(relam),
208-
ObjectIdGetDatum(index->indclass[i]),
166+
ObjectIdGetDatum(index->indclass[i]),
209167
UInt16GetDatum(amstrategy),
210168
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);
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-
* 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'.
377353
*/
378354
List *
379355
find_inheritance_children(Oid inhparent)
@@ -390,8 +366,8 @@ find_inheritance_children(Oid inhparent)
390366

391367
fmgr_info(F_OIDEQ, &key[0].sk_func);
392368
key[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);
395371
relation = heap_openr(InheritsRelationName, AccessShareLock);
396372
scan = heap_beginscan(relation, 0, SnapshotNow, 1, key);
397373
while (HeapTupleIsValid(inheritsTuple = heap_getnext(scan, 0)))

0 commit comments

Comments
 (0)