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)
11201115clause_op ,
11211116test_op ;
11221117Oid opclass_id = InvalidOid ;
1118+ bool found = false;
11231119StrategyNumber pred_strategy = 0 ,
1124- clause_strategy ,
1120+ clause_strategy = 0 ,
11251121test_strategy ;
11261122Expr * test_expr ;
11271123ExprState * test_exprstate ;
11281124Datum test_result ;
11291125bool 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 ;
11351130EState * estate ;
11361131MemoryContext 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 */
11461142if (!is_opclause (predicate ))
11471143return false;
@@ -1174,101 +1170,95 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
11741170clause_op = ((OpExpr * )clause )-> opno ;
11751171
11761172/*
1177- * 1. Finda "btree" strategynumber for the pred_op
1173+ * 1. Find "btree" strategynumbers 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;
12081221break ;
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 'tfind a btree opclass to interpret the operators */
12311230return 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 */
12441236test_strategy = BT_implic_table [clause_strategy - 1 ][pred_strategy - 1 ];
12451237if (test_strategy == 0 )
1246- {
12471238return 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 */
12731263estate = CreateExecutorState ();
12741264
@@ -1298,6 +1288,7 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
12981288
12991289if (isNull )
13001290{
1291+ /* Treat a null result as false ... but it's a tad fishy ... */
13011292elog (DEBUG1 ,"pred_test_simple_clause: null test result" );
13021293return false;
13031294}