@@ -720,7 +720,7 @@ static void
720720handle_const (const Const * c ,
721721const int strategy ,
722722const WalkerContext * context ,
723- WrapperNode * result )/* ret value #1 */
723+ WrapperNode * result )/* ret value #1 */
724724{
725725const PartRelationInfo * prel = context -> prel ;
726726
@@ -838,16 +838,103 @@ handle_const(const Const *c,
838838result -> paramsel = estimate_paramsel_using_prel (prel ,strategy );
839839}
840840
841+ /* Array handler */
842+ static void
843+ handle_array (ArrayType * array ,
844+ const int strategy ,
845+ const bool use_or ,
846+ const WalkerContext * context ,
847+ WrapperNode * result )/* ret value #1 */
848+ {
849+ const PartRelationInfo * prel = context -> prel ;
850+
851+ /* Elements of the array */
852+ Datum * elem_values ;
853+ bool * elem_isnull ;
854+ int elem_count ;
855+
856+ /* Element's properties */
857+ Oid elem_type ;
858+ int16 elem_len ;
859+ bool elem_byval ;
860+ char elem_align ;
861+
862+ /* Check if we can work with this strategy */
863+ if (strategy == 0 )
864+ gotohandle_array_return ;
865+
866+ /* Get element's properties */
867+ elem_type = ARR_ELEMTYPE (array );
868+ get_typlenbyvalalign (elem_type ,& elem_len ,& elem_byval ,& elem_align );
869+
870+ /* Extract values from the array */
871+ deconstruct_array (array ,elem_type ,elem_len ,elem_byval ,elem_align ,
872+ & elem_values ,& elem_isnull ,& elem_count );
873+
874+ /* Handle non-null Const arrays */
875+ if (elem_count > 0 )
876+ {
877+ List * ranges ;
878+ int i ;
879+
880+ /* Set default ranges for OR | AND */
881+ ranges = use_or ?NIL :list_make1_irange_full (prel ,IR_COMPLETE );
882+
883+ /* Select partitions using values */
884+ for (i = 0 ;i < elem_count ;i ++ )
885+ {
886+ WrapperNode wrap ;
887+ Const c ;
888+
889+ NodeSetTag (& c ,T_Const );
890+ c .consttype = elem_type ;
891+ c .consttypmod = -1 ;
892+ c .constcollid = InvalidOid ;
893+ c .constlen = datumGetSize (elem_values [i ],
894+ elem_byval ,
895+ elem_len );
896+ c .constvalue = elem_values [i ];
897+ c .constisnull = elem_isnull [i ];
898+ c .constbyval = elem_byval ;
899+ c .location = -1 ;
900+
901+ handle_const (& c ,strategy ,context ,& wrap );
902+
903+ /* Should we use OR | AND? */
904+ ranges = use_or ?
905+ irange_list_union (ranges ,wrap .rangeset ) :
906+ irange_list_intersection (ranges ,wrap .rangeset );
907+
908+ result -> paramsel = Max (result -> paramsel ,wrap .paramsel );
909+ }
910+
911+ /* Free resources */
912+ pfree (elem_values );
913+ pfree (elem_isnull );
914+
915+ /* Save rangeset */
916+ result -> rangeset = ranges ;
917+
918+ return ;/* done, exit */
919+ }
920+
921+ handle_array_return :
922+ result -> rangeset = list_make1_irange_full (prel ,IR_LOSSY );
923+ result -> paramsel = estimate_paramsel_using_prel (prel ,strategy );
924+ }
925+
841926/* Boolean expression handler */
842927static void
843928handle_boolexpr (const BoolExpr * expr ,
844929const WalkerContext * context ,
845- WrapperNode * result )
930+ WrapperNode * result )/* ret value #1 */
846931{
847- ListCell * lc ;
848- const PartRelationInfo * prel = context -> prel ;
932+ const PartRelationInfo * prel = context -> prel ;
933+ ListCell * lc ;
849934
935+ /* Save expression */
850936result -> orig = (const Node * )expr ;
937+
851938result -> args = NIL ;
852939result -> paramsel = 1.0 ;
853940
@@ -858,22 +945,22 @@ handle_boolexpr(const BoolExpr *expr,
858945
859946foreach (lc ,expr -> args )
860947{
861- WrapperNode * arg_result ;
948+ WrapperNode * wrap ;
862949
863- arg_result = walk_expr_tree ((Expr * )lfirst (lc ),context );
864- result -> args = lappend (result -> args ,arg_result );
950+ wrap = walk_expr_tree ((Expr * )lfirst (lc ),context );
951+ result -> args = lappend (result -> args ,wrap );
865952
866953switch (expr -> boolop )
867954{
868955case OR_EXPR :
869956result -> rangeset = irange_list_union (result -> rangeset ,
870- arg_result -> rangeset );
957+ wrap -> rangeset );
871958break ;
872959
873960case AND_EXPR :
874961result -> rangeset = irange_list_intersection (result -> rangeset ,
875- arg_result -> rangeset );
876- result -> paramsel *=arg_result -> paramsel ;
962+ wrap -> rangeset );
963+ result -> paramsel *=wrap -> paramsel ;
877964break ;
878965
879966default :
@@ -901,107 +988,131 @@ handle_boolexpr(const BoolExpr *expr,
901988static void
902989handle_arrexpr (const ScalarArrayOpExpr * expr ,
903990const WalkerContext * context ,
904- WrapperNode * result )
991+ WrapperNode * result )/* ret value #1 */
905992{
906- Node * exprnode = (Node * )linitial (expr -> args );
907- Node * arraynode = (Node * )lsecond (expr -> args );
993+ Node * part_expr = (Node * )linitial (expr -> args );
994+ Node * array = (Node * )lsecond (expr -> args );
908995const PartRelationInfo * prel = context -> prel ;
909996TypeCacheEntry * tce ;
910997int strategy ;
911998
912- result -> orig = (const Node * )expr ;
913-
914999tce = lookup_type_cache (prel -> ev_type ,TYPECACHE_BTREE_OPFAMILY );
9151000strategy = get_op_opfamily_strategy (expr -> opno ,tce -> btree_opf );
9161001
917- if (!match_expr_to_operand (context -> prel_expr ,exprnode ))
1002+ /* Check if expression tree is a partitioning expression */
1003+ if (!match_expr_to_operand (context -> prel_expr ,part_expr ))
9181004gotohandle_arrexpr_return ;
9191005
920- /* Handle non-null Const arrays */
921- if (arraynode && IsA (arraynode ,Const )&& !((Const * )arraynode )-> constisnull )
922- {
923- ArrayType * arrayval ;
924-
925- int16 elemlen ;
926- bool elembyval ;
927- char elemalign ;
1006+ /* Check if we can work with this strategy */
1007+ if (strategy == 0 )
1008+ gotohandle_arrexpr_return ;
9281009
929- int num_elems ;
1010+ /* Examine the array node */
1011+ switch (nodeTag (array ))
1012+ {
1013+ case T_Const :
1014+ {
1015+ Const * c = (Const * )array ;
9301016
931- Datum * elem_values ;
932- bool * elem_isnull ;
1017+ /* Array is NULL */
1018+ if (c -> constisnull )
1019+ gotohandle_arrexpr_return ;
9331020
934- WalkerContext nested_wcxt ;
935- List * ranges ;
936- int i ;
1021+ /* Examine array */
1022+ handle_array ( DatumGetArrayTypeP ( c -> constvalue ),
1023+ strategy , expr -> useOr , context , result ) ;
9371024
938- /*Extract values from array */
939- arrayval = DatumGetArrayTypeP ((( Const * )arraynode ) -> constvalue ) ;
1025+ /*Save expression */
1026+ result -> orig = ( const Node * )expr ;
9401027
941- get_typlenbyvalalign ( ARR_ELEMTYPE ( arrayval ),
942- & elemlen , & elembyval , & elemalign );
1028+ return ; /* done, exit */
1029+ }
9431030
944- deconstruct_array (arrayval ,
945- ARR_ELEMTYPE (arrayval ),
946- elemlen ,elembyval ,elemalign ,
947- & elem_values ,& elem_isnull ,& num_elems );
1031+ case T_ArrayExpr :
1032+ {
1033+ ArrayExpr * arr_expr = (ArrayExpr * )array ;
1034+ Oid elem_type = arr_expr -> element_typeid ;
1035+ bool array_has_params = false;
1036+ List * ranges ;
1037+ ListCell * lc ;
9481038
949- /* Copy WalkerContext */
950- memcpy ((void * )& nested_wcxt ,
951- (const void * )context ,
952- sizeof (WalkerContext ));
1039+ /* Set default ranges for OR | AND */
1040+ ranges = expr -> useOr ?NIL :list_make1_irange_full (prel ,IR_COMPLETE );
9531041
954- /* Set default ranges for OR | AND */
955- ranges = expr -> useOr ?NIL :list_make1_irange_full (prel ,IR_COMPLETE );
1042+ /* Walk trough elements list */
1043+ foreach (lc ,arr_expr -> elements )
1044+ {
1045+ Node * elem = lfirst (lc );
1046+ WrapperNode wrap ;
9561047
957- /* Select partitions using values */
958- for (i = 0 ;i < num_elems ;i ++ )
959- {
960- WrapperNode sub_result ;
961- Const c ;
1048+ /* Stop if ALL + quals evaluate to NIL */
1049+ if (!expr -> useOr && ranges == NIL )
1050+ break ;
9621051
963- NodeSetTag (& c ,T_Const );
964- c .consttype = ARR_ELEMTYPE (arrayval );
965- c .consttypmod = -1 ;
966- c .constcollid = InvalidOid ;
967- c .constlen = datumGetSize (elem_values [i ],
968- elembyval ,
969- elemlen );
970- c .constvalue = elem_values [i ];
971- c .constisnull = elem_isnull [i ];
972- c .constbyval = elembyval ;
973- c .location = -1 ;
1052+ /* Is this a const value? */
1053+ if (IsConstValue (elem ,context ))
1054+ {
1055+ Const * c = ExtractConst (elem ,context );
1056+
1057+ /* Is this an array?.. */
1058+ if (c -> consttype != elem_type )
1059+ {
1060+ /* Array is NULL */
1061+ if (c -> constisnull )
1062+ gotohandle_arrexpr_return ;
1063+
1064+ /* Examine array */
1065+ handle_array (DatumGetArrayTypeP (c -> constvalue ),
1066+ strategy ,expr -> useOr ,context ,& wrap );
1067+ }
1068+ /* ... or a single element? */
1069+ else handle_const (c ,strategy ,context ,& wrap );
1070+
1071+ /* Should we use OR | AND? */
1072+ ranges = expr -> useOr ?
1073+ irange_list_union (ranges ,wrap .rangeset ) :
1074+ irange_list_intersection (ranges ,wrap .rangeset );
1075+ }
1076+ else array_has_params = true;/* we have non-const nodes */
1077+ }
9741078
975- handle_const (& c ,strategy ,& nested_wcxt ,& sub_result );
1079+ /* Check for PARAM-related optimizations */
1080+ if (array_has_params )
1081+ {
1082+ /* We can't say anything if PARAMs + ANY */
1083+ if (expr -> useOr )
1084+ gotohandle_arrexpr_return ;
9761085
977- ranges = expr -> useOr ?
978- irange_list_union (ranges ,sub_result . rangeset ) :
979- irange_list_intersection ( ranges , sub_result . rangeset );
1086+ /* Recheck condition on a narrowed set of partitions */
1087+ ranges = irange_list_set_lossiness (ranges ,IR_LOSSY );
1088+ }
9801089
981- result -> paramsel = Max ( result -> paramsel , sub_result . paramsel );
982- }
1090+ /* Save rangeset */
1091+ result -> rangeset = ranges ;
9831092
984- result -> rangeset = ranges ;
985- if (num_elems == 0 )
986- result -> paramsel = 0.0 ;
1093+ /* Save expression */
1094+ result -> orig = (const Node * )expr ;
9871095
988- /* Free resources */
989- pfree (elem_values );
990- pfree (elem_isnull );
1096+ return ;/* done, exit */
1097+ }
9911098
992- return ;/* done, exit */
1099+ default :
1100+ break ;
9931101}
9941102
9951103handle_arrexpr_return :
9961104result -> rangeset = list_make1_irange_full (prel ,IR_LOSSY );
9971105result -> paramsel = estimate_paramsel_using_prel (prel ,strategy );
1106+
1107+ /* Save expression */
1108+ result -> orig = (const Node * )expr ;
9981109}
9991110
10001111/* Operator expression handler */
10011112static void
10021113handle_opexpr (const OpExpr * expr ,
10031114const WalkerContext * context ,
1004- WrapperNode * result )
1115+ WrapperNode * result )/* ret value #1 */
10051116{
10061117Node * param ;
10071118const PartRelationInfo * prel = context -> prel ;