@@ -720,7 +720,7 @@ static void
720
720
handle_const (const Const * c ,
721
721
const int strategy ,
722
722
const WalkerContext * context ,
723
- WrapperNode * result ) /* ret value #1 */
723
+ WrapperNode * result ) /* ret value #1 */
724
724
{
725
725
const PartRelationInfo * prel = context -> prel ;
726
726
@@ -838,16 +838,103 @@ handle_const(const Const *c,
838
838
result -> paramsel = estimate_paramsel_using_prel (prel , strategy );
839
839
}
840
840
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
+ goto handle_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
+
841
926
/* Boolean expression handler */
842
927
static void
843
928
handle_boolexpr (const BoolExpr * expr ,
844
929
const WalkerContext * context ,
845
- WrapperNode * result )
930
+ WrapperNode * result ) /* ret value #1 */
846
931
{
847
- ListCell * lc ;
848
- const PartRelationInfo * prel = context -> prel ;
932
+ const PartRelationInfo * prel = context -> prel ;
933
+ ListCell * lc ;
849
934
935
+ /* Save expression */
850
936
result -> orig = (const Node * ) expr ;
937
+
851
938
result -> args = NIL ;
852
939
result -> paramsel = 1.0 ;
853
940
@@ -858,22 +945,22 @@ handle_boolexpr(const BoolExpr *expr,
858
945
859
946
foreach (lc , expr -> args )
860
947
{
861
- WrapperNode * arg_result ;
948
+ WrapperNode * wrap ;
862
949
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 );
865
952
866
953
switch (expr -> boolop )
867
954
{
868
955
case OR_EXPR :
869
956
result -> rangeset = irange_list_union (result -> rangeset ,
870
- arg_result -> rangeset );
957
+ wrap -> rangeset );
871
958
break ;
872
959
873
960
case AND_EXPR :
874
961
result -> rangeset = irange_list_intersection (result -> rangeset ,
875
- arg_result -> rangeset );
876
- result -> paramsel *= arg_result -> paramsel ;
962
+ wrap -> rangeset );
963
+ result -> paramsel *= wrap -> paramsel ;
877
964
break ;
878
965
879
966
default :
@@ -901,107 +988,131 @@ handle_boolexpr(const BoolExpr *expr,
901
988
static void
902
989
handle_arrexpr (const ScalarArrayOpExpr * expr ,
903
990
const WalkerContext * context ,
904
- WrapperNode * result )
991
+ WrapperNode * result ) /* ret value #1 */
905
992
{
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 );
908
995
const PartRelationInfo * prel = context -> prel ;
909
996
TypeCacheEntry * tce ;
910
997
int strategy ;
911
998
912
- result -> orig = (const Node * ) expr ;
913
-
914
999
tce = lookup_type_cache (prel -> ev_type , TYPECACHE_BTREE_OPFAMILY );
915
1000
strategy = get_op_opfamily_strategy (expr -> opno , tce -> btree_opf );
916
1001
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 ))
918
1004
goto handle_arrexpr_return ;
919
1005
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
+ goto handle_arrexpr_return ;
928
1009
929
- int num_elems ;
1010
+ /* Examine the array node */
1011
+ switch (nodeTag (array ))
1012
+ {
1013
+ case T_Const :
1014
+ {
1015
+ Const * c = (Const * ) array ;
930
1016
931
- Datum * elem_values ;
932
- bool * elem_isnull ;
1017
+ /* Array is NULL */
1018
+ if (c -> constisnull )
1019
+ goto handle_arrexpr_return ;
933
1020
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 ) ;
937
1024
938
- /* Extract values from array */
939
- arrayval = DatumGetArrayTypeP ((( Const * ) arraynode ) -> constvalue ) ;
1025
+ /* Save expression */
1026
+ result -> orig = ( const Node * ) expr ;
940
1027
941
- get_typlenbyvalalign ( ARR_ELEMTYPE ( arrayval ),
942
- & elemlen , & elembyval , & elemalign );
1028
+ return ; /* done, exit */
1029
+ }
943
1030
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 ;
948
1038
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 );
953
1041
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 ;
956
1047
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 ;
962
1051
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
+ goto handle_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
+ }
974
1078
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
+ goto handle_arrexpr_return ;
976
1085
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
+ }
980
1089
981
- result -> paramsel = Max ( result -> paramsel , sub_result . paramsel );
982
- }
1090
+ /* Save rangeset */
1091
+ result -> rangeset = ranges ;
983
1092
984
- result -> rangeset = ranges ;
985
- if (num_elems == 0 )
986
- result -> paramsel = 0.0 ;
1093
+ /* Save expression */
1094
+ result -> orig = (const Node * ) expr ;
987
1095
988
- /* Free resources */
989
- pfree (elem_values );
990
- pfree (elem_isnull );
1096
+ return ; /* done, exit */
1097
+ }
991
1098
992
- return ; /* done, exit */
1099
+ default :
1100
+ break ;
993
1101
}
994
1102
995
1103
handle_arrexpr_return :
996
1104
result -> rangeset = list_make1_irange_full (prel , IR_LOSSY );
997
1105
result -> paramsel = estimate_paramsel_using_prel (prel , strategy );
1106
+
1107
+ /* Save expression */
1108
+ result -> orig = (const Node * ) expr ;
998
1109
}
999
1110
1000
1111
/* Operator expression handler */
1001
1112
static void
1002
1113
handle_opexpr (const OpExpr * expr ,
1003
1114
const WalkerContext * context ,
1004
- WrapperNode * result )
1115
+ WrapperNode * result ) /* ret value #1 */
1005
1116
{
1006
1117
Node * param ;
1007
1118
const PartRelationInfo * prel = context -> prel ;
0 commit comments