fix/transform-restrict-val
Onur Tirtir 2022-01-25 16:10:28 +03:00
parent 577224cf23
commit 68c8555733
5 changed files with 92 additions and 35 deletions

View File

@ -5083,6 +5083,10 @@ get_rule_expr_paren(Node *node, deparse_context *context,
} }
#include "distributed/shard_pruning.h"
static void
TransformBinaryOpExprConst(OpExpr *opexpr);
/* ---------- /* ----------
* get_rule_expr - Parse back an expression * get_rule_expr - Parse back an expression
* *
@ -5228,9 +5232,11 @@ get_rule_expr(Node *node, deparse_context *context,
break; break;
case T_OpExpr: case T_OpExpr:
get_oper_expr((OpExpr *) node, context); {
break; TransformBinaryOpExprConst((OpExpr *) node);
get_oper_expr((OpExpr *) node, context);
break;
}
case T_DistinctExpr: case T_DistinctExpr:
{ {
DistinctExpr *expr = (DistinctExpr *) node; DistinctExpr *expr = (DistinctExpr *) node;
@ -6309,6 +6315,67 @@ get_rule_expr(Node *node, deparse_context *context,
} }
} }
/*
* transform CoerceViaIO -> Const
*/
static void
TransformBinaryOpExprConst(OpExpr *opexpr)
{
RelabelType *relabelPtr = NULL;
Var *var = NULL;
if (list_length(opexpr->args) != 2)
{
return;
}
Node *arg1 = linitial(opexpr->args);
Node *arg2 = lsecond(opexpr->args);
if (IsA(arg1, RelabelType) && IsA(arg2, Var))
{
relabelPtr = (RelabelType *) arg1;
var = (Var *) arg2;
}
else if (IsA(arg1, Var) && IsA(arg2, RelabelType))
{
var = (Var *) arg1;
relabelPtr = (RelabelType *) arg2;
}
else
{
/* not a "Var OP RelabelType" or "RelabelType OR Var" */
return;
}
/*
* TODO: Probably need to consider multiple casts too ?
*/
if (!IsA(relabelPtr->arg, CoerceViaIO))
{
return;
}
if (!IsA(((CoerceViaIO *) relabelPtr->arg)->arg, Const))
{
return;
}
/*
* return NULL if TransformVarRestrictionValue fails to transform
* and issue DEBUG1
*/
bool missingOk = true;
Const *transformedValue =
TransformVarRestrictionValue(var, ((Const *)((CoerceViaIO *) relabelPtr->arg)->arg), missingOk);
if (transformedValue)
{
relabelPtr->arg = ((Expr *) transformedValue);
}
}
/* /*
* get_rule_expr_toplevel - Parse back a toplevel expression * get_rule_expr_toplevel - Parse back a toplevel expression
* *

View File

@ -563,7 +563,7 @@ ShardPlacementForFunctionColocatedWithDistTable(DistObjectCacheEntry *procedure,
{ {
bool missingOk = false; bool missingOk = false;
partitionValue = partitionValue =
TransformPartitionRestrictionValue(partitionColumn, partitionValue, TransformVarRestrictionValue(partitionColumn, partitionValue,
missingOk); missingOk);
} }

View File

@ -2632,7 +2632,7 @@ TargetShardIntervalForFastPathQuery(Query *query, bool *isMultiShardQuery,
{ {
bool missingOk = false; bool missingOk = false;
inputDistributionKeyValue = inputDistributionKeyValue =
TransformPartitionRestrictionValue(distributionKey, TransformVarRestrictionValue(distributionKey,
inputDistributionKeyValue, missingOk); inputDistributionKeyValue, missingOk);
} }
@ -2966,7 +2966,7 @@ BuildRoutesForInsert(Query *query, DeferredErrorMessage **planningError)
* FuncExpr coercions for casts created with CREATE CAST ... WITH * FuncExpr coercions for casts created with CREATE CAST ... WITH
* FUNCTION .. AS IMPLICIT. To support this first we strip them here. * FUNCTION .. AS IMPLICIT. To support this first we strip them here.
* Then we do the coercion manually below using * Then we do the coercion manually below using
* TransformPartitionRestrictionValue, if the types are not the same. * TransformVarRestrictionValue, if the types are not the same.
* *
* NOTE: eval_const_expressions below would do some of these removals * NOTE: eval_const_expressions below would do some of these removals
* too, but it's unclear if it would do all of them. It is possible * too, but it's unclear if it would do all of them. It is possible
@ -3012,7 +3012,7 @@ BuildRoutesForInsert(Query *query, DeferredErrorMessage **planningError)
{ {
bool missingOk = false; bool missingOk = false;
partitionValueConst = partitionValueConst =
TransformPartitionRestrictionValue(partitionColumn, TransformVarRestrictionValue(partitionColumn,
partitionValueConst, partitionValueConst,
missingOk); missingOk);
} }

View File

@ -257,7 +257,7 @@ static bool SAORestrictions(ScalarArrayOpExpr *arrayOperatorExpression,
Var *partitionColumn, Var *partitionColumn,
List **requestedRestrictions); List **requestedRestrictions);
static void ErrorTypesDontMatch(Oid firstType, Oid firstCollId, Oid secondType, static void ErrorTypesDontMatch(Oid firstType, Oid firstCollId, Oid secondType,
Oid secondCollId); Oid secondCollId, int elevel);
static bool IsValidHashRestriction(OpExpr *opClause); static bool IsValidHashRestriction(OpExpr *opClause);
static void AddHashRestrictionToInstance(ClauseWalkerContext *context, OpExpr *opClause, static void AddHashRestrictionToInstance(ClauseWalkerContext *context, OpExpr *opClause,
Var *varClause, Const *constantClause); Var *varClause, Const *constantClause);
@ -1106,7 +1106,7 @@ AddPartitionKeyRestrictionToInstance(ClauseWalkerContext *context, OpExpr *opCla
if (constantClause->consttype != partitionColumn->vartype) if (constantClause->consttype != partitionColumn->vartype)
{ {
/* we want our restriction value in terms of the type of the partition column */ /* we want our restriction value in terms of the type of the partition column */
constantClause = TransformPartitionRestrictionValue(partitionColumn, constantClause = TransformVarRestrictionValue(partitionColumn,
constantClause, true); constantClause, true);
if (constantClause == NULL) if (constantClause == NULL)
{ {
@ -1212,33 +1212,27 @@ AddPartitionKeyRestrictionToInstance(ClauseWalkerContext *context, OpExpr *opCla
/* /*
* TransformPartitionRestrictionValue works around how PostgreSQL sometimes * TransformVarRestrictionValue works around how PostgreSQL sometimes
* chooses to try to wrap our Var in a coercion rather than the Const. * chooses to try to wrap our Var in a coercion rather than the Const.
* To deal with this, we strip coercions from both and manually coerce * To deal with this, we strip coercions from both and manually coerce
* the Const into the type of our partition column. * the Const into the type of our partition column.
* It is conceivable that in some instances this may not be possible,
* in those cases we will simply fail to prune partitions based on this clause.
*/ */
Const * Const *
TransformPartitionRestrictionValue(Var *partitionColumn, Const *restrictionValue, TransformVarRestrictionValue(Var *var, Const *restrictionValue, bool missingOk)
bool missingOk)
{ {
Node *transformedValue = coerce_to_target_type(NULL, (Node *) restrictionValue, Node *transformedValue = coerce_to_target_type(NULL, (Node *) restrictionValue,
restrictionValue->consttype, restrictionValue->consttype,
partitionColumn->vartype, var->vartype,
partitionColumn->vartypmod, var->vartypmod,
COERCION_ASSIGNMENT, COERCION_ASSIGNMENT,
COERCE_IMPLICIT_CAST, -1); COERCE_IMPLICIT_CAST, -1);
/* if NULL, no implicit coercion is possible between the types */ /* if NULL, no implicit coercion is possible between the types */
if (transformedValue == NULL) if (transformedValue == NULL)
{ {
if (!missingOk) int elevel = missingOk ? DEBUG1 : ERROR;
{ ErrorTypesDontMatch(var->vartype, var->varcollid, restrictionValue->consttype,
ErrorTypesDontMatch(partitionColumn->vartype, partitionColumn->varcollid, restrictionValue->constcollid, elevel);
restrictionValue->consttype,
restrictionValue->constcollid);
}
return NULL; return NULL;
} }
@ -1252,12 +1246,9 @@ TransformPartitionRestrictionValue(Var *partitionColumn, Const *restrictionValue
/* if still not a constant, no immutable coercion matched */ /* if still not a constant, no immutable coercion matched */
if (!IsA(transformedValue, Const)) if (!IsA(transformedValue, Const))
{ {
if (!missingOk) int elevel = missingOk ? DEBUG1 : ERROR;
{ ErrorTypesDontMatch(var->vartype, var->varcollid, restrictionValue->consttype,
ErrorTypesDontMatch(partitionColumn->vartype, partitionColumn->varcollid, restrictionValue->constcollid, elevel);
restrictionValue->consttype,
restrictionValue->constcollid);
}
return NULL; return NULL;
} }
@ -1270,7 +1261,8 @@ TransformPartitionRestrictionValue(Var *partitionColumn, Const *restrictionValue
* ErrorTypesDontMatch throws an error explicitly printing the type names. * ErrorTypesDontMatch throws an error explicitly printing the type names.
*/ */
static void static void
ErrorTypesDontMatch(Oid firstType, Oid firstCollId, Oid secondType, Oid secondCollId) ErrorTypesDontMatch(Oid firstType, Oid firstCollId, Oid secondType, Oid secondCollId,
int elevel)
{ {
Datum firstTypename = Datum firstTypename =
DirectFunctionCall1Coll(regtypeout, firstCollId, ObjectIdGetDatum(firstType)); DirectFunctionCall1Coll(regtypeout, firstCollId, ObjectIdGetDatum(firstType));
@ -1278,9 +1270,9 @@ ErrorTypesDontMatch(Oid firstType, Oid firstCollId, Oid secondType, Oid secondCo
Datum secondTypename = Datum secondTypename =
DirectFunctionCall1Coll(regtypeout, secondCollId, ObjectIdGetDatum(secondType)); DirectFunctionCall1Coll(regtypeout, secondCollId, ObjectIdGetDatum(secondType));
ereport(ERROR, (errmsg("Cannot coerce %s to %s", ereport(elevel, (errmsg("Cannot coerce %s to %s",
DatumGetCString(secondTypename), DatumGetCString(secondTypename),
DatumGetCString(firstTypename)))); DatumGetCString(firstTypename))));
} }

View File

@ -21,9 +21,7 @@ extern List * PruneShards(Oid relationId, Index rangeTableId, List *whereClauseL
Const **partitionValueConst); Const **partitionValueConst);
extern bool ContainsFalseClause(List *whereClauseList); extern bool ContainsFalseClause(List *whereClauseList);
extern List * get_all_actual_clauses(List *restrictinfo_list); extern List * get_all_actual_clauses(List *restrictinfo_list);
extern Const * TransformPartitionRestrictionValue(Var *partitionColumn, extern Const * TransformVarRestrictionValue(Var *var, Const *restrictionValue, bool missingOk);
Const *restrictionValue,
bool missingOk);
bool VarConstOpExprClause(OpExpr *opClause, Var **varClause, Const **constantClause); bool VarConstOpExprClause(OpExpr *opClause, Var **varClause, Const **constantClause);
#endif /* SHARD_PRUNING_H_ */ #endif /* SHARD_PRUNING_H_ */