9
9
*
10
10
*
11
11
* 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 $
13
13
*
14
14
*-------------------------------------------------------------------------
15
15
*/
16
16
#include "postgres.h"
17
17
18
18
#include <math.h>
19
19
20
- #include "access/heapam.h"
21
20
#include "access/nbtree.h"
22
- #include "catalog/catname.h"
23
21
#include "catalog/pg_amop.h"
24
22
#include "catalog/pg_namespace.h"
25
23
#include "catalog/pg_operator.h"
24
+ #include "catalog/pg_type.h"
26
25
#include "executor/executor.h"
27
26
#include "nodes/makefuncs.h"
28
- #include "nodes/nodeFuncs.h"
29
27
#include "optimizer/clauses.h"
30
28
#include "optimizer/cost.h"
31
29
#include "optimizer/pathnode.h"
32
30
#include "optimizer/paths.h"
33
31
#include "optimizer/restrictinfo.h"
34
32
#include "optimizer/var.h"
35
- #include "parser/parse_coerce.h"
36
- #include "parser/parse_expr.h"
37
- #include "parser/parse_oper.h"
38
33
#include "rewrite/rewriteManip.h"
39
34
#include "utils/builtins.h"
40
- #include "utils/fmgroids .h"
35
+ #include "utils/catcache .h"
41
36
#include "utils/lsyscache.h"
42
37
#include "utils/selfuncs.h"
43
38
#include "utils/syscache.h"
@@ -1120,18 +1115,18 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
1120
1115
clause_op ,
1121
1116
test_op ;
1122
1117
Oid opclass_id = InvalidOid ;
1118
+ bool found = false;
1123
1119
StrategyNumber pred_strategy = 0 ,
1124
- clause_strategy ,
1120
+ clause_strategy = 0 ,
1125
1121
test_strategy ;
1126
1122
Expr * test_expr ;
1127
1123
ExprState * test_exprstate ;
1128
1124
Datum test_result ;
1129
1125
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 ;
1135
1130
EState * estate ;
1136
1131
MemoryContext oldcontext ;
1137
1132
@@ -1141,7 +1136,8 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
1141
1136
1142
1137
/*
1143
1138
* 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?)
1145
1141
*/
1146
1142
if (!is_opclause (predicate ))
1147
1143
return false;
@@ -1174,101 +1170,95 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
1174
1170
clause_op = ((OpExpr * ) clause )-> opno ;
1175
1171
1176
1172
/*
1177
- * 1. Find a "btree" strategy number for the pred_op
1173
+ * 1. Find "btree" strategy numbers for the pred_op and clause_op.
1178
1174
*
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.
1185
1180
*/
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 );
1193
1184
1194
- while (( tuple = heap_getnext ( scan , ForwardScanDirection )) != NULL )
1185
+ for ( i = 0 ; i < catlist -> n_members ; i ++ )
1195
1186
{
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 ))
1198
1212
{
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 );
1202
1214
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;
1208
1221
break ;
1209
1222
}
1210
1223
}
1211
1224
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 );
1220
1226
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 )
1229
1228
{
1230
- /* clause operator isn 't btree-indexable, or isn't in this opclass */
1229
+ /* couldn 't find a btree opclass to interpret the operators */
1231
1230
return false;
1232
1231
}
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 );
1240
1232
1241
1233
/*
1242
- * 3 . Look up the "test" strategy number in the implication table
1234
+ * 2 . Look up the "test" strategy number in the implication table
1243
1235
*/
1244
1236
test_strategy = BT_implic_table [clause_strategy - 1 ][pred_strategy - 1 ];
1245
1237
if (test_strategy == 0 )
1246
- {
1247
1238
return false; /* the implication cannot be determined */
1248
- }
1249
1239
1250
1240
/*
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
1252
1242
*/
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 ))
1258
1248
{
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 ) ;
1262
1252
}
1263
- aform = (Form_pg_amop ) GETSTRUCT (tuple );
1253
+ test_form = (Form_pg_amop ) GETSTRUCT (test_tuple );
1264
1254
1265
1255
/* Get the test operator */
1266
- test_op = aform -> amopopr ;
1256
+ test_op = test_form -> amopopr ;
1267
1257
1268
- ReleaseSysCache (tuple );
1258
+ ReleaseSysCache (test_tuple );
1269
1259
1270
1260
/*
1271
- * 5 . Evaluate the test. For this we need an EState.
1261
+ * 4 . Evaluate the test. For this we need an EState.
1272
1262
*/
1273
1263
estate = CreateExecutorState ();
1274
1264
@@ -1298,6 +1288,7 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
1298
1288
1299
1289
if (isNull )
1300
1290
{
1291
+ /* Treat a null result as false ... but it's a tad fishy ... */
1301
1292
elog (DEBUG1 , "pred_test_simple_clause: null test result" );
1302
1293
return false;
1303
1294
}
0 commit comments