Skip to content

Commit 863172d

Browse files
committed
return commutator from IsKeyOpParam() in case of PARAM OP EXPR
1 parent 4d9822c commit 863172d

File tree

3 files changed

+141
-57
lines changed

3 files changed

+141
-57
lines changed

expected/pathman_basic.out

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,14 @@ EXPLAIN (COSTS OFF) SELECT * FROM test.hash_rel WHERE value = 2;
441441
Filter: (value = 2)
442442
(3 rows)
443443

444+
EXPLAIN (COSTS OFF) SELECT * FROM test.hash_rel WHERE 2 = value; /* test commutator */
445+
QUERY PLAN
446+
------------------------------
447+
Append
448+
-> Seq Scan on hash_rel_1
449+
Filter: (2 = value)
450+
(3 rows)
451+
444452
EXPLAIN (COSTS OFF) SELECT * FROM test.hash_rel WHERE value = 2 OR value = 1;
445453
QUERY PLAN
446454
------------------------------
@@ -451,6 +459,23 @@ EXPLAIN (COSTS OFF) SELECT * FROM test.hash_rel WHERE value = 2 OR value = 1;
451459
Filter: (value = 1)
452460
(5 rows)
453461

462+
EXPLAIN (COSTS OFF) SELECT * FROM test.num_range_rel WHERE 2500 = id; /* test commutator */
463+
QUERY PLAN
464+
-----------------------------------
465+
Append
466+
-> Seq Scan on num_range_rel_3
467+
Filter: (2500 = id)
468+
(3 rows)
469+
470+
EXPLAIN (COSTS OFF) SELECT * FROM test.num_range_rel WHERE 2500 < id; /* test commutator */
471+
QUERY PLAN
472+
-----------------------------------
473+
Append
474+
-> Seq Scan on num_range_rel_3
475+
Filter: (2500 < id)
476+
-> Seq Scan on num_range_rel_4
477+
(4 rows)
478+
454479
EXPLAIN (COSTS OFF) SELECT * FROM test.num_range_rel WHERE id > 2500;
455480
QUERY PLAN
456481
-----------------------------------
@@ -501,6 +526,16 @@ EXPLAIN (COSTS OFF) SELECT * FROM test.range_rel WHERE dt > '2015-02-15';
501526
-> Seq Scan on range_rel_4
502527
(5 rows)
503528

529+
EXPLAIN (COSTS OFF) SELECT * FROM test.range_rel WHERE '2015-02-15' < dt; /* test commutator */
530+
QUERY PLAN
531+
--------------------------------------------------------------------------------
532+
Append
533+
-> Seq Scan on range_rel_2
534+
Filter: ('Sun Feb 15 00:00:00 2015'::timestamp without time zone < dt)
535+
-> Seq Scan on range_rel_3
536+
-> Seq Scan on range_rel_4
537+
(5 rows)
538+
504539
EXPLAIN (COSTS OFF) SELECT * FROM test.range_rel WHERE dt >= '2015-02-01' AND dt < '2015-03-01';
505540
QUERY PLAN
506541
-------------------------------
@@ -565,6 +600,14 @@ EXPLAIN (COSTS OFF) SELECT * FROM test.hash_rel WHERE value = 2;
565600
Filter: (value = 2)
566601
(3 rows)
567602

603+
EXPLAIN (COSTS OFF) SELECT * FROM test.hash_rel WHERE 2 = value; /* test commutator */
604+
QUERY PLAN
605+
------------------------------
606+
Append
607+
-> Seq Scan on hash_rel_1
608+
Filter: (2 = value)
609+
(3 rows)
610+
568611
EXPLAIN (COSTS OFF) SELECT * FROM test.hash_rel WHERE value = 2 OR value = 1;
569612
QUERY PLAN
570613
------------------------------
@@ -575,6 +618,23 @@ EXPLAIN (COSTS OFF) SELECT * FROM test.hash_rel WHERE value = 2 OR value = 1;
575618
Filter: (value = 1)
576619
(5 rows)
577620

621+
EXPLAIN (COSTS OFF) SELECT * FROM test.num_range_rel WHERE 2500 = id; /* test commutator */
622+
QUERY PLAN
623+
----------------------------------------------------------------
624+
Append
625+
-> Index Scan using num_range_rel_3_pkey on num_range_rel_3
626+
Index Cond: (2500 = id)
627+
(3 rows)
628+
629+
EXPLAIN (COSTS OFF) SELECT * FROM test.num_range_rel WHERE 2500 < id; /* test commutator */
630+
QUERY PLAN
631+
----------------------------------------------------------------
632+
Append
633+
-> Index Scan using num_range_rel_3_pkey on num_range_rel_3
634+
Index Cond: (2500 < id)
635+
-> Seq Scan on num_range_rel_4
636+
(4 rows)
637+
578638
EXPLAIN (COSTS OFF) SELECT * FROM test.num_range_rel WHERE id > 2500;
579639
QUERY PLAN
580640
----------------------------------------------------------------
@@ -645,6 +705,16 @@ EXPLAIN (COSTS OFF) SELECT * FROM test.range_rel WHERE dt > '2015-02-15';
645705
-> Seq Scan on range_rel_4
646706
(5 rows)
647707

708+
EXPLAIN (COSTS OFF) SELECT * FROM test.range_rel WHERE '2015-02-15' < dt; /* test commutator */
709+
QUERY PLAN
710+
------------------------------------------------------------------------------------
711+
Append
712+
-> Index Scan using range_rel_2_dt_idx on range_rel_2
713+
Index Cond: ('Sun Feb 15 00:00:00 2015'::timestamp without time zone < dt)
714+
-> Seq Scan on range_rel_3
715+
-> Seq Scan on range_rel_4
716+
(5 rows)
717+
648718
EXPLAIN (COSTS OFF) SELECT * FROM test.range_rel WHERE dt >= '2015-02-01' AND dt < '2015-03-01';
649719
QUERY PLAN
650720
-------------------------------

sql/pathman_basic.sql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,14 +158,18 @@ EXPLAIN (COSTS OFF) SELECT * FROM test.hash_rel;
158158
EXPLAIN (COSTS OFF) SELECT * FROM test.hash_rel WHERE false;
159159
EXPLAIN (COSTS OFF) SELECT * FROM test.hash_rel WHERE value = NULL;
160160
EXPLAIN (COSTS OFF) SELECT * FROM test.hash_rel WHERE value = 2;
161+
EXPLAIN (COSTS OFF) SELECT * FROM test.hash_rel WHERE 2 = value; /* test commutator */
161162
EXPLAIN (COSTS OFF) SELECT * FROM test.hash_rel WHERE value = 2 OR value = 1;
162163

164+
EXPLAIN (COSTS OFF) SELECT * FROM test.num_range_rel WHERE 2500 = id; /* test commutator */
165+
EXPLAIN (COSTS OFF) SELECT * FROM test.num_range_rel WHERE 2500 < id; /* test commutator */
163166
EXPLAIN (COSTS OFF) SELECT * FROM test.num_range_rel WHERE id > 2500;
164167
EXPLAIN (COSTS OFF) SELECT * FROM test.num_range_rel WHERE id >= 1000 AND id < 3000;
165168
EXPLAIN (COSTS OFF) SELECT * FROM test.num_range_rel WHERE id >= 1500 AND id < 2500;
166169
EXPLAIN (COSTS OFF) SELECT * FROM test.num_range_rel WHERE (id >= 500 AND id < 1500) OR (id > 2500);
167170

168171
EXPLAIN (COSTS OFF) SELECT * FROM test.range_rel WHERE dt > '2015-02-15';
172+
EXPLAIN (COSTS OFF) SELECT * FROM test.range_rel WHERE '2015-02-15' < dt; /* test commutator */
169173
EXPLAIN (COSTS OFF) SELECT * FROM test.range_rel WHERE dt >= '2015-02-01' AND dt < '2015-03-01';
170174
EXPLAIN (COSTS OFF) SELECT * FROM test.range_rel WHERE dt >= '2015-02-15' AND dt < '2015-03-15';
171175
EXPLAIN (COSTS OFF) SELECT * FROM test.range_rel WHERE (dt >= '2015-01-15' AND dt < '2015-02-15') OR (dt > '2015-03-15');
@@ -179,8 +183,11 @@ EXPLAIN (COSTS OFF) SELECT * FROM test.hash_rel;
179183
EXPLAIN (COSTS OFF) SELECT * FROM test.hash_rel WHERE false;
180184
EXPLAIN (COSTS OFF) SELECT * FROM test.hash_rel WHERE value = NULL;
181185
EXPLAIN (COSTS OFF) SELECT * FROM test.hash_rel WHERE value = 2;
186+
EXPLAIN (COSTS OFF) SELECT * FROM test.hash_rel WHERE 2 = value; /* test commutator */
182187
EXPLAIN (COSTS OFF) SELECT * FROM test.hash_rel WHERE value = 2 OR value = 1;
183188

189+
EXPLAIN (COSTS OFF) SELECT * FROM test.num_range_rel WHERE 2500 = id; /* test commutator */
190+
EXPLAIN (COSTS OFF) SELECT * FROM test.num_range_rel WHERE 2500 < id; /* test commutator */
184191
EXPLAIN (COSTS OFF) SELECT * FROM test.num_range_rel WHERE id > 2500;
185192
EXPLAIN (COSTS OFF) SELECT * FROM test.num_range_rel WHERE id >= 1000 AND id < 3000;
186193
EXPLAIN (COSTS OFF) SELECT * FROM test.num_range_rel WHERE id >= 1500 AND id < 2500;
@@ -189,6 +196,7 @@ EXPLAIN (COSTS OFF) SELECT * FROM test.num_range_rel ORDER BY id;
189196
EXPLAIN (COSTS OFF) SELECT * FROM test.num_range_rel WHERE id <= 2500 ORDER BY id;
190197

191198
EXPLAIN (COSTS OFF) SELECT * FROM test.range_rel WHERE dt > '2015-02-15';
199+
EXPLAIN (COSTS OFF) SELECT * FROM test.range_rel WHERE '2015-02-15' < dt; /* test commutator */
192200
EXPLAIN (COSTS OFF) SELECT * FROM test.range_rel WHERE dt >= '2015-02-01' AND dt < '2015-03-01';
193201
EXPLAIN (COSTS OFF) SELECT * FROM test.range_rel WHERE dt >= '2015-02-15' AND dt < '2015-03-15';
194202
EXPLAIN (COSTS OFF) SELECT * FROM test.range_rel WHERE (dt >= '2015-01-15' AND dt < '2015-02-15') OR (dt > '2015-03-15');

src/pg_pathman.c

Lines changed: 63 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@
3939
PG_MODULE_MAGIC;
4040

4141

42-
Oid pathman_config_relid = InvalidOid,
43-
pathman_config_params_relid = InvalidOid;
42+
Oid pathman_config_relid = InvalidOid,
43+
pathman_config_params_relid = InvalidOid;
4444

4545

4646
/* pg module functions */
@@ -75,10 +75,6 @@ static void handle_opexpr(const OpExpr *expr,
7575
const WalkerContext *context,
7676
WrapperNode *result);
7777

78-
static bool is_key_op_param(const OpExpr *expr,
79-
const WalkerContext *context,
80-
Node **param_ptr);
81-
8278
static Datum array_find_min_max(Datum *values,
8379
bool *isnull,
8480
int length,
@@ -212,6 +208,47 @@ ExtractConst(Node *node, const WalkerContext *context)
212208
value, isnull, get_typbyval(typid));
213209
}
214210

211+
/*
212+
* Checks if expression is a KEY OP PARAM or PARAM OP KEY,
213+
* where KEY is partitioning expression and PARAM is whatever.
214+
*
215+
* Returns:
216+
* operator's Oid if KEY is a partitioning expr,
217+
* otherwise InvalidOid.
218+
*/
219+
static Oid
220+
IsKeyOpParam(const OpExpr *expr,
221+
const WalkerContext *context,
222+
Node **param_ptr) /* ret value #1 */
223+
{
224+
Node *left = linitial(expr->args),
225+
*right = lsecond(expr->args);
226+
227+
/* Check number of arguments */
228+
if (list_length(expr->args) != 2)
229+
return InvalidOid;
230+
231+
/* KEY OP PARAM */
232+
if (match_expr_to_operand(context->prel_expr, left))
233+
{
234+
*param_ptr = right;
235+
236+
/* return the same operator */
237+
return expr->opno;
238+
}
239+
240+
/* PARAM OP KEY */
241+
if (match_expr_to_operand(context->prel_expr, right))
242+
{
243+
*param_ptr = left;
244+
245+
/* commute to (KEY OP PARAM) */
246+
return get_commutator(expr->opno);
247+
}
248+
249+
return InvalidOid;
250+
}
251+
215252
/* Selectivity estimator for common 'paramsel' */
216253
static inline double
217254
estimate_paramsel_using_prel(const PartRelationInfo *prel, int strategy)
@@ -1315,37 +1352,35 @@ handle_opexpr(const OpExpr *expr,
13151352
{
13161353
Node *param;
13171354
const PartRelationInfo *prel = context->prel;
1355+
Oid opid; /* operator's Oid */
13181356

13191357
/* Save expression */
13201358
result->orig = (const Node *) expr;
13211359

1322-
if (list_length(expr->args) == 2)
1360+
/* Is it KEY OP PARAM or PARAM OP KEY? */
1361+
if (OidIsValid(opid = IsKeyOpParam(expr, context, &param)))
13231362
{
1324-
/* Is it KEY OP PARAM or PARAM OP KEY? */
1325-
if (is_key_op_param(expr, context, &param))
1326-
{
1327-
TypeCacheEntry *tce;
1328-
int strategy;
1363+
TypeCacheEntry *tce;
1364+
int strategy;
13291365

1330-
tce = lookup_type_cache(prel->ev_type, TYPECACHE_BTREE_OPFAMILY);
1331-
strategy = get_op_opfamily_strategy(expr->opno, tce->btree_opf);
1366+
tce = lookup_type_cache(prel->ev_type, TYPECACHE_BTREE_OPFAMILY);
1367+
strategy = get_op_opfamily_strategy(opid, tce->btree_opf);
13321368

1333-
if (IsConstValue(param, context))
1334-
{
1335-
handle_const(ExtractConst(param, context),
1336-
expr->inputcollid,
1337-
strategy, context, result);
1369+
if (IsConstValue(param, context))
1370+
{
1371+
handle_const(ExtractConst(param, context),
1372+
expr->inputcollid,
1373+
strategy, context, result);
13381374

1339-
return; /* done, exit */
1340-
}
1341-
/* TODO: estimate selectivity for param if it's Var */
1342-
else if (IsA(param, Param) || IsA(param, Var))
1343-
{
1344-
result->rangeset = list_make1_irange_full(prel, IR_LOSSY);
1345-
result->paramsel = estimate_paramsel_using_prel(prel, strategy);
1375+
return; /* done, exit */
1376+
}
1377+
/* TODO: estimate selectivity for param if it's Var */
1378+
else if (IsA(param, Param) || IsA(param, Var))
1379+
{
1380+
result->rangeset = list_make1_irange_full(prel, IR_LOSSY);
1381+
result->paramsel = estimate_paramsel_using_prel(prel, strategy);
13461382

1347-
return; /* done, exit */
1348-
}
1383+
return; /* done, exit */
13491384
}
13501385
}
13511386

@@ -1354,35 +1389,6 @@ handle_opexpr(const OpExpr *expr,
13541389
}
13551390

13561391

1357-
/*
1358-
* Checks if expression is a KEY OP PARAM or PARAM OP KEY, where
1359-
* KEY is partitioning expression and PARAM is whatever.
1360-
*
1361-
* NOTE: returns false if partition key is not in expression.
1362-
*/
1363-
static bool
1364-
is_key_op_param(const OpExpr *expr,
1365-
const WalkerContext *context,
1366-
Node **param_ptr) /* ret value #1 */
1367-
{
1368-
Node *left = linitial(expr->args),
1369-
*right = lsecond(expr->args);
1370-
1371-
if (match_expr_to_operand(context->prel_expr, left))
1372-
{
1373-
*param_ptr = right;
1374-
return true;
1375-
}
1376-
1377-
if (match_expr_to_operand(context->prel_expr, right))
1378-
{
1379-
*param_ptr = left;
1380-
return true;
1381-
}
1382-
1383-
return false;
1384-
}
1385-
13861392
/* Find Max or Min value of array */
13871393
static Datum
13881394
array_find_min_max(Datum *values,

0 commit comments

Comments
 (0)