Skip to content

Commit cd5e53b

Browse files
committed
fix for variables wrapped into RelabelType
1 parent 115dc68 commit cd5e53b

File tree

2 files changed

+107
-35
lines changed

2 files changed

+107
-35
lines changed

src/init.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -362,9 +362,10 @@ load_check_constraints(Oid parent_oid, Snapshot snapshot)
362362
case PT_RANGE:
363363
if (!validate_range_constraint(expr, prel, &min, &max))
364364
{
365-
elog(WARNING, "Range constraint for relation %u MUST have exact format: "
365+
elog(WARNING, "Wrong CHECK constraint for relation '%s'. "
366+
"It MUST have exact format: "
366367
"VARIABLE >= CONST AND VARIABLE < CONST. Skipping...",
367-
(Oid) con->conrelid);
368+
get_rel_name(con->conrelid));
368369
continue;
369370
}
370371

@@ -387,9 +388,9 @@ load_check_constraints(Oid parent_oid, Snapshot snapshot)
387388
case PT_HASH:
388389
if (!validate_hash_constraint(expr, prel, &hash))
389390
{
390-
elog(WARNING, "Hash constraint for relation %u MUST have exact format: "
391-
"VARIABLE %% CONST = CONST. Skipping...",
392-
(Oid) con->conrelid);
391+
elog(WARNING, "Wrong CHECK constraint format for relation '%s'. "
392+
"Skipping...",
393+
get_rel_name(con->conrelid));
393394
continue;
394395
}
395396
children[hash] = con->conrelid;
@@ -546,11 +547,15 @@ validate_hash_constraint(Expr *expr, PartRelationInfo *prel, int *hash)
546547

547548
/* Check that function is the base hash function for the type */
548549
funcexpr = (FuncExpr *) first;
549-
if (funcexpr->funcid != prel->hash_proc || !IsA(linitial(funcexpr->args), Var))
550+
if (funcexpr->funcid != prel->hash_proc ||
551+
(!IsA(linitial(funcexpr->args), Var) && !IsA(linitial(funcexpr->args), RelabelType)))
550552
return false;
551553

552554
/* Check that argument is partitioning key attribute */
553-
var = (Var *) linitial(funcexpr->args);
555+
if (IsA(linitial(funcexpr->args), RelabelType))
556+
var = (Var *) ((RelabelType *) linitial(funcexpr->args))->arg;
557+
else
558+
var = (Var *) linitial(funcexpr->args);
554559
if (var->varattno != prel->attnum)
555560
return false;
556561

src/pg_pathman.c

Lines changed: 95 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,16 @@ static bool disable_inheritance_subselect_walker(Node *node, void *context);
7979
/* Expression tree handlers */
8080
static Datum increase_hashable_value(const PartRelationInfo *prel, Datum value);
8181
static 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);
8384
static WrapperNode *handle_opexpr(const OpExpr *expr, WalkerContext *context);
8485
static WrapperNode *handle_boolexpr(const BoolExpr *expr, WalkerContext *context);
8586
static WrapperNode *handle_arrexpr(const ScalarArrayOpExpr *expr, WalkerContext *context);
8687
static void change_varnos_in_restrinct_info(RestrictInfo *rinfo, change_varno_context *context);
8788
static void change_varnos(Node *node, Oid old_varno, Oid new_varno);
8889
static bool change_varno_walker(Node *node, change_varno_context *context);
8990
static 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 */
9294
static void set_plain_rel_size(PlannerInfo *root, RelOptInfo *rel,
@@ -966,7 +968,7 @@ decrease_hashable_value(const PartRelationInfo *prel, Datum value)
966968
*/
967969
static void
968970
handle_binary_opexpr(WalkerContext *context, WrapperNode *result,
969-
const Var *v, const Const *c)
971+
const Node *varnode, const Const *c)
970972
{
971973
HashRelationKey key;
972974
RangeRelation *rangerel;
@@ -978,18 +980,25 @@ handle_binary_opexpr(WalkerContext *context, WrapperNode *result,
978980
is_greater;
979981
FmgrInfo cmp_func;
980982
Oid cmp_proc_oid;
983+
Oid vartype;
981984
const OpExpr *expr = (const OpExpr *)result->orig;
982985
TypeCacheEntry *tce;
983986
const 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,
987996
TYPECACHE_BTREE_OPFAMILY | TYPECACHE_CMP_PROC | TYPECACHE_CMP_PROC_FINFO);
988997

989998
strategy = get_op_opfamily_strategy(expr->opno, tce->btree_opf);
990999
cmp_proc_oid = get_opfamily_proc(tce->btree_opf,
1000+
vartype,
9911001
c->consttype,
992-
prel->atttype,
9931002
BTORDER_PROC);
9941003
fmgr_info(cmp_proc_oid, &cmp_func);
9951004

@@ -1032,6 +1041,7 @@ handle_binary_opexpr(WalkerContext *context, WrapperNode *result,
10321041
result->rangeset = list_make1_irange(make_irange(key.hash, key.hash, true));
10331042
return;
10341043
}
1044+
break;
10351045
case PT_RANGE:
10361046
value = c->constvalue;
10371047
rangerel = get_pathman_range_relation(prel->key.relid, NULL);
@@ -1191,14 +1201,21 @@ handle_binary_opexpr(WalkerContext *context, WrapperNode *result,
11911201
*/
11921202
static void
11931203
handle_binary_opexpr_param(const PartRelationInfo *prel,
1194-
WrapperNode *result, const Var *v)
1204+
WrapperNode *result, const Node *varnode)
11951205
{
11961206
const OpExpr *expr = (const OpExpr *)result->orig;
11971207
TypeCacheEntry *tce;
11981208
int 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);
12021219
strategy = get_op_opfamily_strategy(expr->opno, tce->btree_opf);
12031220

12041221
result->rangeset = list_make1_irange(make_irange(0, prel->children_count - 1, true));
@@ -1306,38 +1323,24 @@ static WrapperNode *
13061323
handle_opexpr(const OpExpr *expr, WalkerContext *context)
13071324
{
13081325
WrapperNode *result = (WrapperNode *)palloc(sizeof(WrapperNode));
1309-
Node *firstarg = NULL,
1310-
*secondarg = NULL;
1326+
Node *var, *param;
13111327
const PartRelationInfo *prel = context->prel;
13121328

13131329
result->orig = (const Node *)expr;
13141330
result->args = NIL;
13151331

13161332
if (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));
13361339
return 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);
13411344
return result;
13421345
}
13431346
}
@@ -1348,6 +1351,54 @@ handle_opexpr(const OpExpr *expr, WalkerContext *context)
13481351
return 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
{
14151466
WrapperNode *result = (WrapperNode *)palloc(sizeof(WrapperNode));
14161467
Node *varnode = (Node *) linitial(expr->args);
1468+
Var *var;
14171469
Node *arraynode = (Node *) lsecond(expr->args);
14181470
int hash;
14191471
const PartRelationInfo *prel = context->prel;
@@ -1422,8 +1474,18 @@ handle_arrexpr(const ScalarArrayOpExpr *expr, WalkerContext *context)
14221474
result->args = NIL;
14231475
result->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+
goto handle_arrexpr_return;
1487+
}
1488+
else
14271489
goto handle_arrexpr_return;
14281490

14291491
if (arraynode && IsA(arraynode, Const) &&
@@ -1437,6 +1499,8 @@ handle_arrexpr(const ScalarArrayOpExpr *expr, WalkerContext *context)
14371499
Datum *elem_values;
14381500
bool *elem_nulls;
14391501
int i;
1502+
Datum value;
1503+
uint32 int_value;
14401504

14411505
/* Extract values from array */
14421506
arrayval = DatumGetArrayTypeP(((Const *) arraynode)->constvalue);
@@ -1452,7 +1516,10 @@ handle_arrexpr(const ScalarArrayOpExpr *expr, WalkerContext *context)
14521516
/* Construct OIDs list */
14531517
for (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);
14561523
result->rangeset = irange_list_union(result->rangeset,
14571524
list_make1_irange(make_irange(hash, hash, true)));
14581525
}

0 commit comments

Comments
 (0)