Skip to content

Commit 1c9ac7d

Browse files
committed
Change pg_amop's index on (amopclaid,amopopr) to index (amopopr,amopclaid).
This makes no difference for existing uses, but allows SelectSortFunction() and pred_test_simple_clause() to use indexscans instead of seqscans to locate entries for a particular operator in pg_amop. Better yet, they can use the SearchSysCacheList() API to cache the search results.
1 parent 30f6094 commit 1c9ac7d

File tree

6 files changed

+96
-108
lines changed

6 files changed

+96
-108
lines changed

src/backend/optimizer/path/indxpath.c

Lines changed: 71 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -9,35 +9,30 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.136 2003/03/23 01:49:02 tgl Exp $
12+
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.137 2003/05/13 04:38:58 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
1616
#include "postgres.h"
1717

1818
#include <math.h>
1919

20-
#include "access/heapam.h"
2120
#include "access/nbtree.h"
22-
#include "catalog/catname.h"
2321
#include "catalog/pg_amop.h"
2422
#include "catalog/pg_namespace.h"
2523
#include "catalog/pg_operator.h"
24+
#include "catalog/pg_type.h"
2625
#include "executor/executor.h"
2726
#include "nodes/makefuncs.h"
28-
#include "nodes/nodeFuncs.h"
2927
#include "optimizer/clauses.h"
3028
#include "optimizer/cost.h"
3129
#include "optimizer/pathnode.h"
3230
#include "optimizer/paths.h"
3331
#include "optimizer/restrictinfo.h"
3432
#include "optimizer/var.h"
35-
#include "parser/parse_coerce.h"
36-
#include "parser/parse_expr.h"
37-
#include "parser/parse_oper.h"
3833
#include "rewrite/rewriteManip.h"
3934
#include "utils/builtins.h"
40-
#include "utils/fmgroids.h"
35+
#include "utils/catcache.h"
4136
#include "utils/lsyscache.h"
4237
#include "utils/selfuncs.h"
4338
#include "utils/syscache.h"
@@ -1120,18 +1115,18 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
11201115
clause_op,
11211116
test_op;
11221117
Oid opclass_id = InvalidOid;
1118+
bool found = false;
11231119
StrategyNumber pred_strategy = 0,
1124-
clause_strategy,
1120+
clause_strategy = 0,
11251121
test_strategy;
11261122
Expr *test_expr;
11271123
ExprState *test_exprstate;
11281124
Datum test_result;
11291125
bool isNull;
1130-
Relation relation;
1131-
HeapScanDesc scan;
1132-
HeapTuple tuple;
1133-
ScanKeyData entry[1];
1134-
Form_pg_amop aform;
1126+
HeapTuple test_tuple;
1127+
Form_pg_amop test_form;
1128+
CatCList *catlist;
1129+
int i;
11351130
EState *estate;
11361131
MemoryContext oldcontext;
11371132

@@ -1141,7 +1136,8 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
11411136

11421137
/*
11431138
* Can't do anything more unless they are both binary opclauses with a
1144-
* Var on the left and a Const on the right.
1139+
* Var on the left and a Const on the right. (XXX someday try to
1140+
* commute Const/Var cases?)
11451141
*/
11461142
if (!is_opclause(predicate))
11471143
return false;
@@ -1174,101 +1170,95 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
11741170
clause_op = ((OpExpr *) clause)->opno;
11751171

11761172
/*
1177-
* 1. Find a "btree" strategy number for the pred_op
1173+
* 1. Find "btree" strategy numbers for the pred_op and clause_op.
11781174
*
1179-
* The following assumes that any given operator will only be in a single
1180-
* btree operator class. This is true at least for all the
1181-
* pre-defined operator classes. If it isn't true, then whichever
1182-
* operator class happens to be returned first for the given operator
1183-
* will be used to find the associated strategy numbers for the test.
1184-
* --Nels, Jan '93
1175+
* We must find a btree opclass that contains both operators, else the
1176+
* implication can't be determined. If there are multiple such opclasses,
1177+
* assume we can use any one to determine the logical relationship of the
1178+
* two operators and the correct corresponding test operator. This should
1179+
* work for any logically consistent opclasses.
11851180
*/
1186-
ScanKeyEntryInitialize(&entry[0], 0x0,
1187-
Anum_pg_amop_amopopr,
1188-
F_OIDEQ,
1189-
ObjectIdGetDatum(pred_op));
1190-
1191-
relation = heap_openr(AccessMethodOperatorRelationName, AccessShareLock);
1192-
scan = heap_beginscan(relation, SnapshotNow, 1, entry);
1181+
catlist = SearchSysCacheList(AMOPOPID, 1,
1182+
ObjectIdGetDatum(pred_op),
1183+
0, 0, 0);
11931184

1194-
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
1185+
for (i = 0; i < catlist->n_members; i++)
11951186
{
1196-
aform = (Form_pg_amop) GETSTRUCT(tuple);
1197-
if (opclass_is_btree(aform->amopclaid))
1187+
HeapTuple pred_tuple = &catlist->members[i]->tuple;
1188+
Form_pg_amop pred_form = (Form_pg_amop) GETSTRUCT(pred_tuple);
1189+
HeapTuple clause_tuple;
1190+
1191+
if (!opclass_is_btree(pred_form->amopclaid))
1192+
continue;
1193+
1194+
/* Get the predicate operator's btree strategy number */
1195+
pred_strategy = (StrategyNumber) pred_form->amopstrategy;
1196+
Assert(pred_strategy >= 1 && pred_strategy <= 5);
1197+
1198+
/*
1199+
* Remember which operator class this strategy number came from
1200+
*/
1201+
opclass_id = pred_form->amopclaid;
1202+
1203+
/*
1204+
* From the same opclass, find a strategy num for the clause_op,
1205+
* if possible
1206+
*/
1207+
clause_tuple = SearchSysCache(AMOPOPID,
1208+
ObjectIdGetDatum(clause_op),
1209+
ObjectIdGetDatum(opclass_id),
1210+
0, 0);
1211+
if (HeapTupleIsValid(clause_tuple))
11981212
{
1199-
/* Get the predicate operator's btree strategy number (1 to 5) */
1200-
pred_strategy = (StrategyNumber) aform->amopstrategy;
1201-
Assert(pred_strategy >= 1 && pred_strategy <= 5);
1213+
Form_pg_amop clause_form = (Form_pg_amop) GETSTRUCT(clause_tuple);
12021214

1203-
/*
1204-
* Remember which operator class this strategy number came
1205-
* from
1206-
*/
1207-
opclass_id = aform->amopclaid;
1215+
/* Get the restriction clause operator's strategy number */
1216+
clause_strategy = (StrategyNumber) clause_form->amopstrategy;
1217+
Assert(clause_strategy >= 1 && clause_strategy <= 5);
1218+
1219+
ReleaseSysCache(clause_tuple);
1220+
found = true;
12081221
break;
12091222
}
12101223
}
12111224

1212-
heap_endscan(scan);
1213-
heap_close(relation, AccessShareLock);
1214-
1215-
if (!OidIsValid(opclass_id))
1216-
{
1217-
/* predicate operator isn't btree-indexable */
1218-
return false;
1219-
}
1225+
ReleaseSysCacheList(catlist);
12201226

1221-
/*
1222-
* 2. From the same opclass, find a strategy num for the clause_op
1223-
*/
1224-
tuple = SearchSysCache(AMOPOPID,
1225-
ObjectIdGetDatum(opclass_id),
1226-
ObjectIdGetDatum(clause_op),
1227-
0, 0);
1228-
if (!HeapTupleIsValid(tuple))
1227+
if (!found)
12291228
{
1230-
/* clause operator isn't btree-indexable, or isn't in this opclass */
1229+
/* couldn't find a btree opclass to interpret the operators */
12311230
return false;
12321231
}
1233-
aform = (Form_pg_amop) GETSTRUCT(tuple);
1234-
1235-
/* Get the restriction clause operator's strategy number (1 to 5) */
1236-
clause_strategy = (StrategyNumber) aform->amopstrategy;
1237-
Assert(clause_strategy >= 1 && clause_strategy <= 5);
1238-
1239-
ReleaseSysCache(tuple);
12401232

12411233
/*
1242-
* 3. Look up the "test" strategy number in the implication table
1234+
* 2. Look up the "test" strategy number in the implication table
12431235
*/
12441236
test_strategy = BT_implic_table[clause_strategy - 1][pred_strategy - 1];
12451237
if (test_strategy == 0)
1246-
{
12471238
return false; /* the implication cannot be determined */
1248-
}
12491239

12501240
/*
1251-
* 4. From the same opclass, find the operator for the test strategy
1241+
* 3. From the same opclass, find the operator for the test strategy
12521242
*/
1253-
tuple = SearchSysCache(AMOPSTRATEGY,
1254-
ObjectIdGetDatum(opclass_id),
1255-
Int16GetDatum(test_strategy),
1256-
0, 0);
1257-
if (!HeapTupleIsValid(tuple))
1243+
test_tuple = SearchSysCache(AMOPSTRATEGY,
1244+
ObjectIdGetDatum(opclass_id),
1245+
Int16GetDatum(test_strategy),
1246+
0, 0);
1247+
if (!HeapTupleIsValid(test_tuple))
12581248
{
1259-
/* this probably shouldn't fail? */
1260-
elog(DEBUG1, "pred_test_simple_clause: unknown test_op");
1261-
return false;
1249+
/* This should not fail, else pg_amop entry is missing */
1250+
elog(ERROR, "Missing pg_amop entry for opclass %u strategy %d",
1251+
opclass_id, test_strategy);
12621252
}
1263-
aform = (Form_pg_amop) GETSTRUCT(tuple);
1253+
test_form = (Form_pg_amop) GETSTRUCT(test_tuple);
12641254

12651255
/* Get the test operator */
1266-
test_op = aform->amopopr;
1256+
test_op = test_form->amopopr;
12671257

1268-
ReleaseSysCache(tuple);
1258+
ReleaseSysCache(test_tuple);
12691259

12701260
/*
1271-
* 5. Evaluate the test. For this we need an EState.
1261+
* 4. Evaluate the test. For this we need an EState.
12721262
*/
12731263
estate = CreateExecutorState();
12741264

@@ -1298,6 +1288,7 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
12981288

12991289
if (isNull)
13001290
{
1291+
/* Treat a null result as false ... but it's a tad fishy ... */
13011292
elog(DEBUG1, "pred_test_simple_clause: null test result");
13021293
return false;
13031294
}

src/backend/utils/cache/lsyscache.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.93 2003/05/09 18:08:48 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.94 2003/05/13 04:38:58 tgl Exp $
1111
*
1212
* NOTES
1313
* Eventually, the index information should go through here, too.
@@ -44,8 +44,8 @@ bool
4444
op_in_opclass(Oid opno, Oid opclass)
4545
{
4646
return SearchSysCacheExists(AMOPOPID,
47-
ObjectIdGetDatum(opclass),
4847
ObjectIdGetDatum(opno),
48+
ObjectIdGetDatum(opclass),
4949
0, 0);
5050
}
5151

@@ -67,8 +67,8 @@ op_requires_recheck(Oid opno, Oid opclass)
6767
bool result;
6868

6969
tp = SearchSysCache(AMOPOPID,
70-
ObjectIdGetDatum(opclass),
7170
ObjectIdGetDatum(opno),
71+
ObjectIdGetDatum(opclass),
7272
0, 0);
7373
if (!HeapTupleIsValid(tp))
7474
elog(ERROR, "op_requires_recheck: op %u is not a member of opclass %u",

src/backend/utils/cache/syscache.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.87 2002/09/04 20:31:30 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.88 2003/05/13 04:38:58 tgl Exp $
1212
*
1313
* NOTES
1414
* These routines allow the parser/planner/executor to perform
@@ -128,8 +128,8 @@ static const struct cachedesc cacheinfo[] = {
128128
0,
129129
2,
130130
{
131-
Anum_pg_amop_amopclaid,
132131
Anum_pg_amop_amopopr,
132+
Anum_pg_amop_amopclaid,
133133
0,
134134
0
135135
}},

src/backend/utils/sort/tuplesort.c

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
* Portions Copyright (c) 1994, Regents of the University of California
7979
*
8080
* IDENTIFICATION
81-
* $Header: /cvsroot/pgsql/src/backend/utils/sort/tuplesort.c,v 1.32 2002/11/13 00:39:48 momjian Exp $
81+
* $Header: /cvsroot/pgsql/src/backend/utils/sort/tuplesort.c,v 1.33 2003/05/13 04:38:58 tgl Exp $
8282
*
8383
*-------------------------------------------------------------------------
8484
*/
@@ -87,18 +87,18 @@
8787

8888
#include "access/heapam.h"
8989
#include "access/nbtree.h"
90-
#include "catalog/catname.h"
9190
#include "catalog/pg_amop.h"
9291
#include "catalog/pg_amproc.h"
9392
#include "catalog/pg_operator.h"
9493
#include "miscadmin.h"
94+
#include "utils/catcache.h"
9595
#include "utils/datum.h"
96-
#include "utils/fmgroids.h"
9796
#include "utils/logtape.h"
9897
#include "utils/lsyscache.h"
9998
#include "utils/syscache.h"
10099
#include "utils/tuplesort.h"
101100

101+
102102
/*
103103
* Possible states of a Tuplesort object. These denote the states that
104104
* persist between calls of Tuplesort routines.
@@ -1708,32 +1708,30 @@ SelectSortFunction(Oid sortOperator,
17081708
RegProcedure *sortFunction,
17091709
SortFunctionKind *kind)
17101710
{
1711-
Relation relation;
1712-
HeapScanDesc scan;
1713-
ScanKeyData skey[1];
1711+
CatCList *catlist;
1712+
int i;
17141713
HeapTuple tuple;
17151714
Form_pg_operator optup;
17161715
Oid opclass = InvalidOid;
17171716

17181717
/*
1719-
* Scan pg_amop to see if the target operator is registered as the "<"
1718+
* Search pg_amop to see if the target operator is registered as the "<"
17201719
* or ">" operator of any btree opclass. It's possible that it might
17211720
* be registered both ways (eg, if someone were to build a "reverse
17221721
* sort" opclass for some reason); prefer the "<" case if so. If the
17231722
* operator is registered the same way in multiple opclasses, assume
17241723
* we can use the associated comparator function from any one.
17251724
*/
1726-
ScanKeyEntryInitialize(&skey[0], 0x0,
1727-
Anum_pg_amop_amopopr,
1728-
F_OIDEQ,
1729-
ObjectIdGetDatum(sortOperator));
1725+
catlist = SearchSysCacheList(AMOPOPID, 1,
1726+
ObjectIdGetDatum(sortOperator),
1727+
0, 0, 0);
17301728

1731-
relation = heap_openr(AccessMethodOperatorRelationName, AccessShareLock);
1732-
scan = heap_beginscan(relation, SnapshotNow, 1, skey);
1733-
1734-
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
1729+
for (i = 0; i < catlist->n_members; i++)
17351730
{
1736-
Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple);
1731+
Form_pg_amop aform;
1732+
1733+
tuple = &catlist->members[i]->tuple;
1734+
aform = (Form_pg_amop) GETSTRUCT(tuple);
17371735

17381736
if (!opclass_is_btree(aform->amopclaid))
17391737
continue;
@@ -1751,8 +1749,7 @@ SelectSortFunction(Oid sortOperator,
17511749
}
17521750
}
17531751

1754-
heap_endscan(scan);
1755-
heap_close(relation, AccessShareLock);
1752+
ReleaseSysCacheList(catlist);
17561753

17571754
if (OidIsValid(opclass))
17581755
{

src/include/catalog/catversion.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
3838
* Portions Copyright (c) 1994, Regents of the University of California
3939
*
40-
* $Id: catversion.h,v 1.191 2003/05/12 23:08:50 tgl Exp $
40+
* $Id: catversion.h,v 1.192 2003/05/13 04:38:58 tgl Exp $
4141
*
4242
*-------------------------------------------------------------------------
4343
*/
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/* yyyymmddN */
56-
#define CATALOG_VERSION_NO 200305121
56+
#define CATALOG_VERSION_NO 200305122
5757

5858
#endif

0 commit comments

Comments
 (0)