3030#include "utils/elog.h"
3131#include "utils/array.h"
3232#include "utils/date.h"
33- #include "utils/lsyscache.h"
3433#include "utils/guc.h"
34+ #include "utils/lsyscache.h"
35+ #include "utils/selfuncs.h"
3536#include "access/heapam.h"
3637#include "access/nbtree.h"
3738#include "storage/ipc.h"
@@ -841,6 +842,7 @@ walk_expr_tree(WalkerContext *wcxt, Expr *expr, const PartRelationInfo *prel)
841842result -> orig = (const Node * )expr ;
842843result -> args = NIL ;
843844result -> rangeset = list_make1_irange (make_irange (0 ,prel -> children_count - 1 , true));
845+ result -> paramsel = 1.0 ;
844846return result ;
845847}
846848}
@@ -866,8 +868,7 @@ handle_binary_opexpr(const PartRelationInfo *prel, WrapperNode *result,
866868TypeCacheEntry * tce ;
867869
868870/* Determine operator type */
869- tce = lookup_type_cache (v -> vartype ,
870- TYPECACHE_EQ_OPR |TYPECACHE_LT_OPR |TYPECACHE_GT_OPR |TYPECACHE_CMP_PROC |TYPECACHE_CMP_PROC_FINFO );
871+ tce = lookup_type_cache (v -> vartype ,TYPECACHE_BTREE_OPFAMILY |TYPECACHE_CMP_PROC |TYPECACHE_CMP_PROC_FINFO );
871872strategy = get_op_opfamily_strategy (expr -> opno ,tce -> btree_opf );
872873cmp_proc_oid = get_opfamily_proc (tce -> btree_opf ,
873874c -> consttype ,
@@ -1036,6 +1037,38 @@ handle_binary_opexpr(const PartRelationInfo *prel, WrapperNode *result,
10361037}
10371038
10381039result -> rangeset = list_make1_irange (make_irange (0 ,prel -> children_count - 1 , true));
1040+ result -> paramsel = 1.0 ;
1041+ }
1042+
1043+ /*
1044+ *Estimate selectivity of parametrized quals.
1045+ */
1046+ static void
1047+ handle_binary_opexpr_param (const PartRelationInfo * prel ,
1048+ WrapperNode * result ,const Var * v )
1049+ {
1050+ const OpExpr * expr = (const OpExpr * )result -> orig ;
1051+ TypeCacheEntry * tce ;
1052+ int strategy ;
1053+
1054+ /* Determine operator type */
1055+ tce = lookup_type_cache (v -> vartype ,TYPECACHE_BTREE_OPFAMILY );
1056+ strategy = get_op_opfamily_strategy (expr -> opno ,tce -> btree_opf );
1057+
1058+ result -> rangeset = list_make1_irange (make_irange (0 ,prel -> children_count - 1 , true));
1059+
1060+ if (strategy == BTEqualStrategyNumber )
1061+ {
1062+ result -> paramsel = 1.0 / (double )prel -> children_count ;
1063+ }
1064+ else if (prel -> parttype == PT_RANGE && strategy > 0 )
1065+ {
1066+ result -> paramsel = DEFAULT_INEQ_SEL ;
1067+ }
1068+ else
1069+ {
1070+ result -> paramsel = 1.0 ;
1071+ }
10391072}
10401073
10411074/*
@@ -1135,24 +1168,36 @@ handle_opexpr(WalkerContext *wcxt, const OpExpr *expr, const PartRelationInfo *p
11351168
11361169if (list_length (expr -> args )== 2 )
11371170{
1138- firstarg = (Node * )linitial (expr -> args );
1139- secondarg = (Node * )lsecond (expr -> args );
1140-
1141- if (IsA (firstarg ,Var )&& IsConstValue (wcxt ,secondarg )&&
1142- ((Var * )firstarg )-> varattno == prel -> attnum )
1171+ if (IsA (linitial (expr -> args ),Var )
1172+ && ((Var * )linitial (expr -> args ))-> varattno == prel -> attnum )
11431173{
1144- handle_binary_opexpr ( prel , result , ( Var * )firstarg , ExtractConst ( wcxt , secondarg ) );
1145- return result ;
1174+ firstarg = ( Node * )linitial ( expr -> args );
1175+ secondarg = ( Node * ) lsecond ( expr -> args ) ;
11461176}
1147- else if (IsA (secondarg ,Var )&& IsConstValue ( wcxt , firstarg ) &&
1148- ((Var * )secondarg )-> varattno == prel -> attnum )
1177+ else if (IsA (lsecond ( expr -> args ) ,Var )
1178+ && ((Var * )lsecond ( expr -> args ) )-> varattno == prel -> attnum )
11491179{
1150- handle_binary_opexpr (prel ,result , (Var * )secondarg ,ExtractConst (wcxt ,firstarg ));
1151- return result ;
1180+ firstarg = (Node * )lsecond (expr -> args );
1181+ secondarg = (Node * )linitial (expr -> args );
1182+ }
1183+
1184+ if (firstarg && secondarg )
1185+ {
1186+ if (IsConstValue (wcxt ,secondarg ))
1187+ {
1188+ handle_binary_opexpr (prel ,result , (Var * )firstarg ,ExtractConst (wcxt ,secondarg ));
1189+ return result ;
1190+ }
1191+ else if (IsA (secondarg ,Param )|| IsA (secondarg ,Var ))
1192+ {
1193+ handle_binary_opexpr_param (prel ,result , (Var * )firstarg );
1194+ return result ;
1195+ }
11521196}
11531197}
11541198
11551199result -> rangeset = list_make1_irange (make_irange (0 ,prel -> children_count - 1 , true));
1200+ result -> paramsel = 1.0 ;
11561201return result ;
11571202}
11581203
@@ -1167,6 +1212,7 @@ handle_boolexpr(WalkerContext *wcxt, const BoolExpr *expr, const PartRelationInf
11671212
11681213result -> orig = (const Node * )expr ;
11691214result -> args = NIL ;
1215+ result -> paramsel = 1.0 ;
11701216
11711217if (expr -> boolop == AND_EXPR )
11721218result -> rangeset = list_make1_irange (make_irange (0 ,prel -> children_count - 1 , false));
@@ -1186,13 +1232,28 @@ handle_boolexpr(WalkerContext *wcxt, const BoolExpr *expr, const PartRelationInf
11861232break ;
11871233case AND_EXPR :
11881234result -> rangeset = irange_list_intersect (result -> rangeset ,arg -> rangeset );
1235+ result -> paramsel *=arg -> paramsel ;
11891236break ;
11901237default :
11911238result -> rangeset = list_make1_irange (make_irange (0 ,prel -> children_count - 1 , false));
11921239break ;
11931240}
11941241}
11951242
1243+ if (expr -> boolop == OR_EXPR )
1244+ {
1245+ int totallen = irange_list_length (result -> rangeset );
1246+
1247+ foreach (lc ,result -> args )
1248+ {
1249+ WrapperNode * arg = (WrapperNode * )lfirst (lc );
1250+ int len = irange_list_length (arg -> rangeset );
1251+
1252+ result -> paramsel *= (1.0 - arg -> paramsel * (double )len / (double )totallen );
1253+ }
1254+ result -> paramsel = 1.0 - result -> paramsel ;
1255+ }
1256+
11961257return result ;
11971258}
11981259
@@ -1209,6 +1270,7 @@ handle_arrexpr(WalkerContext *wcxt, const ScalarArrayOpExpr *expr, const PartRel
12091270
12101271result -> orig = (const Node * )expr ;
12111272result -> args = NIL ;
1273+ result -> paramsel = 1.0 ;
12121274
12131275if (varnode == NULL || !IsA (varnode ,Var ))
12141276{
@@ -1254,6 +1316,11 @@ handle_arrexpr(WalkerContext *wcxt, const ScalarArrayOpExpr *expr, const PartRel
12541316return result ;
12551317}
12561318
1319+ if (IsA (arraynode ,Param ))
1320+ {
1321+ result -> paramsel = DEFAULT_INEQ_SEL ;
1322+ }
1323+
12571324result -> rangeset = list_make1_irange (make_irange (0 ,prel -> children_count - 1 , true));
12581325return result ;
12591326}