@@ -79,14 +79,16 @@ static bool disable_inheritance_subselect_walker(Node *node, void *context);
7979/* Expression tree handlers */
8080static Datum increase_hashable_value (const PartRelationInfo * prel ,Datum value );
8181static Datum decrease_hashable_value (const PartRelationInfo * prel ,Datum value );
82- static void handle_binary_opexpr (WalkerContext * context ,WrapperNode * result ,const Var * v ,const Const * c );
82+ static void handle_binary_opexpr (WalkerContext * context ,WrapperNode * result ,const Node * varnode ,const Const * c );
83+ static void handle_binary_opexpr_param (const PartRelationInfo * prel ,WrapperNode * result ,const Node * varnode );
8384static WrapperNode * handle_opexpr (const OpExpr * expr ,WalkerContext * context );
8485static WrapperNode * handle_boolexpr (const BoolExpr * expr ,WalkerContext * context );
8586static WrapperNode * handle_arrexpr (const ScalarArrayOpExpr * expr ,WalkerContext * context );
8687static void change_varnos_in_restrinct_info (RestrictInfo * rinfo ,change_varno_context * context );
8788static void change_varnos (Node * node ,Oid old_varno ,Oid new_varno );
8889static bool change_varno_walker (Node * node ,change_varno_context * context );
8990static RestrictInfo * rebuild_restrictinfo (Node * clause ,RestrictInfo * old_rinfo );
91+ static bool pull_var_param (const WalkerContext * ctx ,const OpExpr * expr ,Node * * var_ptr ,Node * * param_ptr );
9092
9193/* copied from allpaths.h */
9294static void set_plain_rel_size (PlannerInfo * root ,RelOptInfo * rel ,
@@ -966,7 +968,7 @@ decrease_hashable_value(const PartRelationInfo *prel, Datum value)
966968 */
967969static void
968970handle_binary_opexpr (WalkerContext * context ,WrapperNode * result ,
969- const Var * v ,const Const * c )
971+ const Node * varnode ,const Const * c )
970972{
971973HashRelationKey key ;
972974RangeRelation * rangerel ;
@@ -978,18 +980,25 @@ handle_binary_opexpr(WalkerContext *context, WrapperNode *result,
978980is_greater ;
979981FmgrInfo cmp_func ;
980982Oid cmp_proc_oid ;
983+ Oid vartype ;
981984const OpExpr * expr = (const OpExpr * )result -> orig ;
982985TypeCacheEntry * tce ;
983986const PartRelationInfo * prel = context -> prel ;
984987
988+ Assert (IsA (varnode ,Var )|| IsA (varnode ,RelableType ));
989+
990+ vartype = !IsA (varnode ,RelabelType ) ?
991+ ((Var * )varnode )-> vartype :
992+ ((RelabelType * )varnode )-> resulttype ;
993+
985994/* Determine operator type */
986- tce = lookup_type_cache (v -> vartype ,
995+ tce = lookup_type_cache (vartype ,
987996TYPECACHE_BTREE_OPFAMILY |TYPECACHE_CMP_PROC |TYPECACHE_CMP_PROC_FINFO );
988997
989998strategy = get_op_opfamily_strategy (expr -> opno ,tce -> btree_opf );
990999cmp_proc_oid = get_opfamily_proc (tce -> btree_opf ,
1000+ vartype ,
9911001c -> consttype ,
992- prel -> atttype ,
9931002BTORDER_PROC );
9941003fmgr_info (cmp_proc_oid ,& cmp_func );
9951004
@@ -1032,6 +1041,7 @@ handle_binary_opexpr(WalkerContext *context, WrapperNode *result,
10321041result -> rangeset = list_make1_irange (make_irange (key .hash ,key .hash , true));
10331042return ;
10341043}
1044+ break ;
10351045case PT_RANGE :
10361046value = c -> constvalue ;
10371047rangerel = get_pathman_range_relation (prel -> key .relid ,NULL );
@@ -1191,14 +1201,21 @@ handle_binary_opexpr(WalkerContext *context, WrapperNode *result,
11911201 */
11921202static void
11931203handle_binary_opexpr_param (const PartRelationInfo * prel ,
1194- WrapperNode * result ,const Var * v )
1204+ WrapperNode * result ,const Node * varnode )
11951205{
11961206const OpExpr * expr = (const OpExpr * )result -> orig ;
11971207TypeCacheEntry * tce ;
11981208int strategy ;
1209+ Oid vartype ;
1210+
1211+ Assert (IsA (varnode ,Var )|| IsA (varnode ,RelableType ));
1212+
1213+ vartype = !IsA (varnode ,RelabelType ) ?
1214+ ((Var * )varnode )-> vartype :
1215+ ((RelabelType * )varnode )-> resulttype ;
11991216
12001217/* Determine operator type */
1201- tce = lookup_type_cache (v -> vartype ,TYPECACHE_BTREE_OPFAMILY );
1218+ tce = lookup_type_cache (vartype ,TYPECACHE_BTREE_OPFAMILY );
12021219strategy = get_op_opfamily_strategy (expr -> opno ,tce -> btree_opf );
12031220
12041221result -> rangeset = list_make1_irange (make_irange (0 ,prel -> children_count - 1 , true));
@@ -1306,38 +1323,24 @@ static WrapperNode *
13061323handle_opexpr (const OpExpr * expr ,WalkerContext * context )
13071324{
13081325WrapperNode * result = (WrapperNode * )palloc (sizeof (WrapperNode ));
1309- Node * firstarg = NULL ,
1310- * secondarg = NULL ;
1326+ Node * var ,* param ;
13111327const PartRelationInfo * prel = context -> prel ;
13121328
13131329result -> orig = (const Node * )expr ;
13141330result -> args = NIL ;
13151331
13161332if (list_length (expr -> args )== 2 )
13171333{
1318- if (IsA (linitial (expr -> args ),Var )
1319- && ((Var * )linitial (expr -> args ))-> varoattno == prel -> attnum )
1320- {
1321- firstarg = (Node * )linitial (expr -> args );
1322- secondarg = (Node * )lsecond (expr -> args );
1323- }
1324- else if (IsA (lsecond (expr -> args ),Var )
1325- && ((Var * )lsecond (expr -> args ))-> varoattno == prel -> attnum )
1326- {
1327- firstarg = (Node * )lsecond (expr -> args );
1328- secondarg = (Node * )linitial (expr -> args );
1329- }
1330-
1331- if (firstarg && secondarg )
1334+ if (pull_var_param (context ,expr ,& var ,& param ))
13321335{
1333- if (IsConstValue (context ,secondarg ))
1336+ if (IsConstValue (context ,param ))
13341337{
1335- handle_binary_opexpr (context ,result ,( Var * ) firstarg ,ExtractConst (context ,secondarg ));
1338+ handle_binary_opexpr (context ,result ,var ,ExtractConst (context ,param ));
13361339return result ;
13371340}
1338- else if (IsA (secondarg ,Param )|| IsA (secondarg ,Var ))
1341+ else if (IsA (param ,Param )|| IsA (param ,Var ))
13391342{
1340- handle_binary_opexpr_param (prel ,result ,( Var * ) firstarg );
1343+ handle_binary_opexpr_param (prel ,result ,var );
13411344return result ;
13421345}
13431346}
@@ -1348,6 +1351,54 @@ handle_opexpr(const OpExpr *expr, WalkerContext *context)
13481351return result ;
13491352}
13501353
1354+ /*
1355+ * Checks if expression is a KEY OP PARAM or PARAM OP KEY,
1356+ * where KEY is partition key (it could be Var or RelableType) and PARAM is
1357+ * whatever. Function returns variable (or RelableType) and param via var_ptr
1358+ * and param_ptr pointers. If partition key isn't in expression then function
1359+ * returns false.
1360+ */
1361+ static bool
1362+ pull_var_param (const WalkerContext * ctx ,const OpExpr * expr ,Node * * var_ptr ,Node * * param_ptr )
1363+ {
1364+ Node * left = linitial (expr -> args ),
1365+ * right = lsecond (expr -> args );
1366+ Var * v = NULL ;
1367+
1368+ /* Check the case when variable is on the left side */
1369+ if (IsA (left ,Var )|| IsA (left ,RelabelType ))
1370+ {
1371+ v = !IsA (left ,RelabelType ) ?
1372+ (Var * )left :
1373+ (Var * ) ((RelabelType * )left )-> arg ;
1374+
1375+ if (v -> varattno == ctx -> prel -> attnum )
1376+ {
1377+ * var_ptr = left ;
1378+ * param_ptr = right ;
1379+ return true;
1380+ }
1381+ }
1382+
1383+ /* ... variable is on the right side */
1384+ if (IsA (right ,Var )|| IsA (right ,RelabelType ))
1385+ {
1386+ v = !IsA (right ,RelabelType ) ?
1387+ (Var * )right :
1388+ (Var * ) ((RelabelType * )right )-> arg ;
1389+
1390+ if (v -> varattno == ctx -> prel -> attnum )
1391+ {
1392+ * var_ptr = right ;
1393+ * param_ptr = left ;
1394+ return true;
1395+ }
1396+ }
1397+
1398+ /* Variable isn't a partitionig key */
1399+ return false;
1400+ }
1401+
13511402/*
13521403 * Boolean expression handler
13531404 */
@@ -1414,6 +1465,7 @@ handle_arrexpr(const ScalarArrayOpExpr *expr, WalkerContext *context)
14141465{
14151466WrapperNode * result = (WrapperNode * )palloc (sizeof (WrapperNode ));
14161467Node * varnode = (Node * )linitial (expr -> args );
1468+ Var * var ;
14171469Node * arraynode = (Node * )lsecond (expr -> args );
14181470int hash ;
14191471const PartRelationInfo * prel = context -> prel ;
@@ -1422,8 +1474,18 @@ handle_arrexpr(const ScalarArrayOpExpr *expr, WalkerContext *context)
14221474result -> args = NIL ;
14231475result -> paramsel = 1.0 ;
14241476
1477+ Assert (varnode != NULL );
1478+
14251479/* If variable is not the partition key then skip it */
1426- if (!varnode || !IsA (varnode ,Var )|| ((Var * )varnode )-> varattno != prel -> attnum )
1480+ if (IsA (varnode ,Var )|| IsA (varnode ,RelabelType ))
1481+ {
1482+ var = !IsA (varnode ,RelabelType ) ?
1483+ (Var * )varnode :
1484+ (Var * ) ((RelabelType * )varnode )-> arg ;
1485+ if (var -> varattno != prel -> attnum )
1486+ gotohandle_arrexpr_return ;
1487+ }
1488+ else
14271489gotohandle_arrexpr_return ;
14281490
14291491if (arraynode && IsA (arraynode ,Const )&&
@@ -1437,6 +1499,8 @@ handle_arrexpr(const ScalarArrayOpExpr *expr, WalkerContext *context)
14371499Datum * elem_values ;
14381500bool * elem_nulls ;
14391501int i ;
1502+ Datum value ;
1503+ uint32 int_value ;
14401504
14411505/* Extract values from array */
14421506arrayval = DatumGetArrayTypeP (((Const * )arraynode )-> constvalue );
@@ -1452,7 +1516,10 @@ handle_arrexpr(const ScalarArrayOpExpr *expr, WalkerContext *context)
14521516/* Construct OIDs list */
14531517for (i = 0 ;i < num_elems ;i ++ )
14541518{
1455- hash = make_hash (elem_values [i ],prel -> children_count );
1519+ /* Invoke base hash function for value type */
1520+ value = OidFunctionCall1 (prel -> hash_proc ,elem_values [i ]);
1521+ int_value = DatumGetUInt32 (value );
1522+ hash = make_hash (int_value ,prel -> children_count );
14561523result -> rangeset = irange_list_union (result -> rangeset ,
14571524list_make1_irange (make_irange (hash ,hash , true)));
14581525}