Clean up from code review

Only change to behavior is:
- don't ignore array const's constcollid in SAORestrictions
- don't end lines with commas in DebugLogPruningInstance
pull/3486/head
Philip Dubé 2020-02-13 23:24:10 +00:00
parent cdedb98c54
commit 7382c8be00
2 changed files with 216 additions and 214 deletions

View File

@ -7,8 +7,8 @@
* need to be queried to find rows matching the expression in a query.
*
* In PruneShards we first make a compact representation of the given
* query logical tree. This tree represent boolean operators and its
* associated valid constrainst (expression nodes) and whether boolean
* query logical tree. This tree represents boolean operators and its
* associated valid constraints (expression nodes) and whether boolean
* operator has associated unknown constraints. This allows essentially
* unknown constraints to be replaced by a simple placeholder flag.
*
@ -17,7 +17,7 @@
* 1. AND(hash_col IN (1,2), OR(X, X))
* 2. AND(hash_col IN (1,2), OR(X))
* 3. AND(hash_col IN (1,2), X)
* Where X represents any (set of) unrecognized unprunable constraint(s).
* Where X represents any set of unrecognized unprunable constraint(s).
*
* Above allows the following pruning machinery to understand that
* the target shard is determined solely by constraint: hash_col IN (1,2).
@ -38,7 +38,7 @@
* expressions. While (P OR Q) AND (R OR S) is logically equivalent to (P AND
* R) OR (P AND S) OR (Q AND R) OR (Q AND S), in our implementation it becomes
* P OR Q OR R OR S. This is acceptable since this will always result in a
* superset of shards. If this proves to be a issue in practice, a more
* superset of shards. If this proves to be a issue in practice, a more
* complete algorithm could be implemented.
*
* We then evaluate each non-partial pruning instance in the disjunction
@ -93,6 +93,7 @@
#include "utils/memutils.h"
#include "utils/ruleutils.h"
/*
* Tree node for compact representation of the given query logical tree.
* Represent a single boolean operator node and its associated
@ -101,7 +102,7 @@
typedef struct PruningTreeNode
{
/* Indicates is this AND/OR boolean operator */
bool isAnd;
BoolExprType boolop;
/* Does this boolean operator have unknown/unprunable constraint(s) */
bool hasInvalidConstraints;
@ -109,10 +110,7 @@ typedef struct PruningTreeNode
/* List of recognized valid prunable constraints of this boolean opearator */
List *validConstraints;
/*
* Child boolean operators.
* Parent is always different boolean operator from its children.
*/
/* Child boolean producing operators. Parents are always different from their children */
List *childBooleanNodes;
} PruningTreeNode;
@ -140,8 +138,8 @@ typedef struct PruningInstance
bool evaluatesToFalse;
/*
* Constraints on the partition column value. If multiple values are
* found the more restrictive one should be stored here. Even in case of
* Constraints on the partition column value. If multiple values are
* found the more restrictive one should be stored here. Even for
* a hash-partitioned table, actual column-values are stored here, *not*
* hashed values.
*/
@ -168,15 +166,15 @@ typedef struct PruningInstance
/*
* When OR clauses are found, the non-ORed part (think of a < 3 AND (a > 5
* OR a > 7)) of the expression is stored in one PruningInstance which is
* then copied for the ORed expressions. The original is marked as
* isPartial, to avoid it being used for pruning.
* then copied for the ORed expressions. The original is marked as
* isPartial, to avoid being used for pruning.
*/
bool isPartial;
} PruningInstance;
/*
* Partial instances that need to be finished building. This is used to
* Partial instances that need to be finished building. This is used to
* collect all ANDed restrictions, before looking into ORed expressions.
*/
typedef struct PendingPruningInstance
@ -274,32 +272,13 @@ static int LowerShardBoundary(Datum partitionColumnValue,
ShardInterval **shardIntervalCache,
int shardCount, FunctionCallInfo compareFunction,
bool includeMax);
static inline PruningTreeNode * CreatePruningNode(bool isAnd);
static inline OpExpr * SAORestrictionArrayEqualityOp(
ScalarArrayOpExpr *arrayOperatorExpression,
Var *partitionColumn);
static inline void DebugLogNode(char *fmt, Node *node, List *deparseCtx);
static PruningTreeNode * CreatePruningNode(BoolExprType boolop);
static OpExpr * SAORestrictionArrayEqualityOp(ScalarArrayOpExpr *arrayOperatorExpression,
Var *partitionColumn);
static void DebugLogNode(char *fmt, Node *node, List *deparseCtx);
static void DebugLogPruningInstance(PruningInstance *pruning, List *deparseCtx);
static int ConstraintCount(PruningTreeNode *node);
#define AndBooleanNode() (CreatePruningNode(true))
#define OrBooleanNode() (CreatePruningNode(false))
#define IsAndOp(node) ((node)->isAnd)
#define IsOrOp(node) (!(node)->isAnd)
#define ConstraintCount(node) \
(list_length((node)->childBooleanNodes) + \
list_length((node)->validConstraints) + \
((node)->hasInvalidConstraints ? 1 : 0))
#define DebugLogPruningInstance(prune, deparseCtx) \
DebugLogNode("constraint value: %s, ", \
(Node *) (prune)->equalConsts, (deparseCtx)); \
DebugLogNode("constraint (lt) value: %s, ", \
(Node *) (prune)->lessConsts, (deparseCtx)); \
DebugLogNode("constraint (lteq) value: %s, ", \
(Node *) (prune)->lessEqualConsts, (deparseCtx)); \
DebugLogNode("constraint (gt) value: %s, ", \
(Node *) (prune)->greaterConsts, (deparseCtx)); \
DebugLogNode("constraint (gteq) value: %s, ", \
(Node *) (prune)->greaterEqualConsts, (deparseCtx));
/*
* PruneShards returns all shards from a distributed table that cannot be
@ -378,7 +357,7 @@ PruneShards(Oid relationId, Index rangeTableId, List *whereClauseList,
"a partition column comparator")));
}
PruningTreeNode *tree = AndBooleanNode();
PruningTreeNode *tree = CreatePruningNode(AND_EXPR);
PruningTreeBuildContext treeBuildContext = { 0 };
treeBuildContext.current = tree;
@ -393,7 +372,7 @@ PruneShards(Oid relationId, Index rangeTableId, List *whereClauseList,
/* Figure out what we can prune on */
PrunableExpressions(tree, &context);
List *debugLoggedPruningInstances = NULL;
List *debugLoggedPruningInstances = NIL;
/*
* Prune using each of the PrunableInstances we found, and OR results
@ -414,7 +393,7 @@ PruneShards(Oid relationId, Index rangeTableId, List *whereClauseList,
/*
* If the current instance has no prunable expressions, we'll have to
* return all shards. No point in continuing pruning in that case.
* return all shards. No point in continuing pruning in that case.
*/
if (!prune->hasValidConstraint)
{
@ -485,7 +464,7 @@ PruneShards(Oid relationId, Index rangeTableId, List *whereClauseList,
if (IsLoggableLevel(DEBUG3))
{
if (foundRestriction && debugLoggedPruningInstances)
if (foundRestriction && debugLoggedPruningInstances != NIL)
{
List *deparseCtx = deparse_context_for("unknown", relationId);
foreach(pruneCell, debugLoggedPruningInstances)
@ -524,7 +503,7 @@ PruneShards(Oid relationId, Index rangeTableId, List *whereClauseList,
/*
* Check whether node is a valid constraint for pruning
* IsValidConditionNode checks whether node is a valid constraint for pruning.
*/
static bool
IsValidConditionNode(Node *node, Var *partitionColumn)
@ -550,12 +529,7 @@ IsValidConditionNode(Node *node, Var *partitionColumn)
else if (IsA(node, ScalarArrayOpExpr))
{
ScalarArrayOpExpr *arrayOperatorExpression = (ScalarArrayOpExpr *) node;
if (SAORestrictions(arrayOperatorExpression, partitionColumn, NULL))
{
return true;
}
return false;
return SAORestrictions(arrayOperatorExpression, partitionColumn, NULL);
}
else
{
@ -565,7 +539,7 @@ IsValidConditionNode(Node *node, Var *partitionColumn)
/*
* Build a logical tree of valid constraints and invalid constaints for pruning.
* BuildPruningTree builds a logical tree of constraints for pruning.
*/
static bool
BuildPruningTree(Node *node, PruningTreeBuildContext *context)
@ -582,15 +556,14 @@ BuildPruningTree(Node *node, PruningTreeBuildContext *context)
else if (IsA(node, BoolExpr))
{
BoolExpr *boolExpr = (BoolExpr *) node;
bool isAnded = boolExpr->boolop == AND_EXPR;
if (boolExpr->boolop == NOT_EXPR)
{
return false;
}
else if (context->current->isAnd != isAnded)
else if (context->current->boolop != boolExpr->boolop)
{
PruningTreeNode *child = CreatePruningNode(isAnded);
PruningTreeNode *child = CreatePruningNode(boolExpr->boolop);
context->current->childBooleanNodes = lappend(
context->current->childBooleanNodes, child);
@ -624,14 +597,12 @@ BuildPruningTree(Node *node, PruningTreeBuildContext *context)
/*
* Simplifies the logical tree of valid and invalid constraints for pruning.
* SimplifyPruningTree reduces logical tree of valid and invalid constraints for pruning.
* The goal is to remove any node having just a single constraint associated with it.
* This constraint is assigned to the parent logical node.
* Removal of nodes is done by traversing from tree leafs upward.
*
* For example logical tree of
* AND(hash_col = 1, OR(X)) gets simplified into AND(hash_col = 1, X)
* Where X is any unknown condition.
* For example 'AND(hash_col = 1, OR(X))' gets simplified to 'AND(hash_col = 1, X)',
* where X is any unknown condition.
*/
static void
SimplifyPruningTree(PruningTreeNode *node, PruningTreeNode *parent)
@ -649,11 +620,11 @@ SimplifyPruningTree(PruningTreeNode *node, PruningTreeNode *parent)
if (!parent)
{
/* Root is always ANDed expressions */
Assert(IsAndOp(node));
Assert(node->boolop == AND_EXPR);
return;
}
/* Boolean operator with just a single (regocnized/unknown) constraints gets simplified */
/* Boolean operator with single (recognized/unknown) constraint gets simplified */
if (ConstraintCount(node) <= 1)
{
parent->validConstraints = list_concat(parent->validConstraints,
@ -704,19 +675,19 @@ static void
PrunableExpressions(PruningTreeNode *tree, ClauseWalkerContext *context)
{
/*
* Build initial list of prunable expressions. As long as only,
* Build initial list of prunable expressions. As long as only,
* implicitly or explicitly, ANDed expressions are found, this perform a
* depth-first search. When an ORed expression is found, the current
* depth-first search. When an ORed expression is found, the current
* PruningInstance is added to context->pruningInstances (once for each
* ORed expression), then the tree-traversal is continued without
* recursing. Once at the top-level again, we'll process all pending
* recursing. Once at the top-level again, we'll process all pending
* expressions - that allows us to find all ANDed expressions, before
* recursing into an ORed expression.
*/
PrunableExpressionsWalker(tree, context);
/*
* Process all pending instances. While processing, new ones might be
* Process all pending instances. While processing, new ones might be
* added to the list, so don't use foreach().
*
* Check the places in PruningInstanceWalker that push onto
@ -756,15 +727,15 @@ PrunableExpressionsWalker(PruningTreeNode *node, ClauseWalkerContext *context)
return;
}
if (IsOrOp(node))
if (node->boolop == OR_EXPR)
{
/*
* "Queue" partial pruning instances. This is used to convert
* "Queue" partial pruning instances. This is used to convert
* expressions like (A AND (B OR C) AND D) into (A AND B AND D),
* (A AND C AND D), with A, B, C, D being restrictions. When the
* (A AND C AND D), with A, B, C, D being restrictions. When the
* OR is encountered, a reference to the partially built
* PruningInstance (containing A at this point), is added to
* context->pendingInstances once for B and once for C. Once a
* context->pendingInstances once for B and once for C. Once a
* full tree-walk completed, PrunableExpressions() will complete
* the pending instances, which'll now also know about restriction
* D, by calling PrunableExpressionsWalker() once for B and once
@ -773,7 +744,7 @@ PrunableExpressionsWalker(PruningTreeNode *node, ClauseWalkerContext *context)
if (node->hasInvalidConstraints)
{
PruningTreeNode *child = AndBooleanNode();
PruningTreeNode *child = CreatePruningNode(AND_EXPR);
child->hasInvalidConstraints = true;
AddNewConjuction(context, child);
@ -783,7 +754,7 @@ PrunableExpressionsWalker(PruningTreeNode *node, ClauseWalkerContext *context)
{
Node *constraint = (Node *) lfirst(cell);
PruningTreeNode *child = AndBooleanNode();
PruningTreeNode *child = CreatePruningNode(AND_EXPR);
child->validConstraints = list_make1(constraint);
AddNewConjuction(context, child);
@ -792,14 +763,14 @@ PrunableExpressionsWalker(PruningTreeNode *node, ClauseWalkerContext *context)
foreach(cell, node->childBooleanNodes)
{
PruningTreeNode *child = (PruningTreeNode *) lfirst(cell);
Assert(IsAndOp(child));
Assert(child->boolop == AND_EXPR);
AddNewConjuction(context, child);
}
return;
}
Assert(IsAndOp(node));
Assert(node->boolop == AND_EXPR);
foreach(cell, node->validConstraints)
{
@ -881,14 +852,14 @@ PrunableExpressionsWalker(PruningTreeNode *node, ClauseWalkerContext *context)
foreach(cell, node->childBooleanNodes)
{
PruningTreeNode *child = (PruningTreeNode *) lfirst(cell);
Assert(IsOrOp(child));
Assert(child->boolop == OR_EXPR);
PrunableExpressionsWalker(child, context);
}
}
/*
* Check whether expression is a valid comparison of a var to a constant.
* VarConstOpExprClause check whether an expression is a valid comparison of a Var to a Const.
* Also obtaining the var with constant when valid.
*/
static bool
@ -946,21 +917,20 @@ AddSAOPartitionKeyRestrictionToInstance(ClauseWalkerContext *context,
ScalarArrayOpExpr *arrayOperatorExpression)
{
List *restrictions = NULL;
if (SAORestrictions(arrayOperatorExpression, context->partitionColumn, &restrictions))
{
PruningTreeNode *node = OrBooleanNode();
node->validConstraints = restrictions;
AddNewConjuction(context, node);
}
else
{
Assert(false);
}
bool validSAORestriction PG_USED_FOR_ASSERTS_ONLY =
SAORestrictions(arrayOperatorExpression, context->partitionColumn, &restrictions);
Assert(validSAORestriction);
PruningTreeNode *node = CreatePruningNode(OR_EXPR);
node->validConstraints = restrictions;
AddNewConjuction(context, node);
}
/*
* Check whether SAO constraint is valid. Also obtaining the built equality restrictions.
* SAORestrictions checks whether an SAO constraint is valid.
* Also obtains equality restrictions.
*/
static bool
SAORestrictions(ScalarArrayOpExpr *arrayOperatorExpression, Var *partitionColumn,
@ -977,11 +947,12 @@ SAORestrictions(ScalarArrayOpExpr *arrayOperatorExpression, Var *partitionColumn
equal(strippedLeftOpExpression, partitionColumn) &&
IsA(arrayArgument, Const))
{
Const *arrayConst = (Const *) arrayArgument;
int16 typlen = 0;
bool typbyval = false;
char typalign = '\0';
Datum arrayElement = 0;
Datum inArray = ((Const *) arrayArgument)->constvalue;
Datum inArray = arrayConst->constvalue;
bool isNull = false;
bool foundValid = false;
@ -991,7 +962,7 @@ SAORestrictions(ScalarArrayOpExpr *arrayOperatorExpression, Var *partitionColumn
return false;
}
ArrayType *array = DatumGetArrayTypeP(((Const *) arrayArgument)->constvalue);
ArrayType *array = DatumGetArrayTypeP(arrayConst->constvalue);
/* get the necessary information from array type to iterate over it */
Oid elementType = ARR_ELEMTYPE(array);
@ -1018,8 +989,8 @@ SAORestrictions(ScalarArrayOpExpr *arrayOperatorExpression, Var *partitionColumn
if (requestedRestrictions)
{
Const *constElement = makeConst(elementType, -1,
DEFAULT_COLLATION_OID, typlen,
arrayElement,
arrayConst->constcollid,
typlen, arrayElement,
isNull, typbyval);
/* build partcol = arrayelem operator */
@ -1058,7 +1029,7 @@ AddNewConjuction(ClauseWalkerContext *context, PruningTreeNode *node)
/*
* Signal that this instance is not to be used for pruning on
* its own. Once the pending instance is processed, it'll be
* its own. Once the pending instance is processed, it'll be
* used.
*/
instance->instance->isPartial = true;
@ -1067,7 +1038,8 @@ AddNewConjuction(ClauseWalkerContext *context, PruningTreeNode *node)
/*
* Check whether operator clause is valid restriction for partition column.
* IsValidPartitionKeyRestriction check whether an operator clause is
* a valid restriction for comparing to a partition column.
*/
static bool
IsValidPartitionKeyRestriction(OpExpr *opClause)
@ -1216,11 +1188,12 @@ AddPartitionKeyRestrictionToInstance(ClauseWalkerContext *context, OpExpr *opCla
/*
* Sometimes PostgreSQL chooses to try to wrap our Var in a coercion rather
* than the Const; to deal with this, we strip the coercions from both and
* manually coerce 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.
* TransformPartitionRestrictionValue works around how PostgreSQL sometimes
* 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
* 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.
*/
static Const *
TransformPartitionRestrictionValue(Var *partitionColumn, Const *restrictionValue)
@ -1255,7 +1228,7 @@ TransformPartitionRestrictionValue(Var *partitionColumn, Const *restrictionValue
/*
* Check whether operator clause is valid restriction for hashed column.
* IsValidHashRestriction checks whether an operator clause is a valid restriction for hashed column.
*/
static bool
IsValidHashRestriction(OpExpr *opClause)
@ -1293,11 +1266,11 @@ AddHashRestrictionToInstance(ClauseWalkerContext *context, OpExpr *opClause,
Assert(IsValidHashRestriction(opClause));
/*
* Ladidadida, dirty hackety hack. We only add such
* Ladidadida, dirty hackety hack. We only add such
* constraints (in ShardIntervalOpExpressions()) to select a
* shard based on its exact boundaries. For efficient binary
* shard based on its exact boundaries. For efficient binary
* search it's better to simply use one representative value
* to look up the shard. In practice, this is sufficient for
* to look up the shard. In practice, this is sufficient for
* now.
*/
PruningInstance *prune = context->currentPruningInstance;
@ -1394,7 +1367,7 @@ PruneOne(DistTableCacheEntry *cacheEntry, ClauseWalkerContext *context,
/*
* For an equal constraints, if there's no overlapping shards (always the
* case for hash and range partitioning, sometimes for append), can
* perform binary search for the right interval. That's usually the
* perform binary search for the right interval. That's usually the
* fastest, so try that first.
*/
if (prune->equalConsts &&
@ -1414,7 +1387,7 @@ PruneOne(DistTableCacheEntry *cacheEntry, ClauseWalkerContext *context,
/*
* If the hash value we're looking for is known, we can search for the
* interval directly. That's fast and should only ever be the case for a
* interval directly. That's fast and should only ever be the case for a
* hash-partitioned table.
*/
if (prune->hashedEqualConsts)
@ -1435,7 +1408,7 @@ PruneOne(DistTableCacheEntry *cacheEntry, ClauseWalkerContext *context,
{
/*
* equalConst based pruning above yielded a different shard than
* pruning based on pre-hashed equality. This is useful in case
* pruning based on pre-hashed equality. This is useful in case
* of INSERT ... SELECT, where both can occur together (one via
* join/colocation, the other via a plain equality restriction).
*/
@ -1824,8 +1797,7 @@ ExhaustivePrune(DistTableCacheEntry *cacheEntry, ClauseWalkerContext *context,
/*
* ExhaustivePruneOne returns true if curInterval is pruned away, false
* otherwise.
* ExhaustivePruneOne returns whether curInterval is pruned away.
*/
static bool
ExhaustivePruneOne(ShardInterval *curInterval,
@ -1912,11 +1884,11 @@ ExhaustivePruneOne(ShardInterval *curInterval,
/*
* Helper for creating a node for pruning tree
*/
static inline PruningTreeNode *
CreatePruningNode(bool isAnd)
static PruningTreeNode *
CreatePruningNode(BoolExprType boolop)
{
PruningTreeNode *node = palloc0(sizeof(PruningTreeNode));
node->isAnd = isAnd;
node->boolop = boolop;
node->childBooleanNodes = NULL;
node->validConstraints = NULL;
node->hasInvalidConstraints = false;
@ -1925,9 +1897,10 @@ CreatePruningNode(bool isAnd)
/*
* Create equality operator for a single element of scalar array constraint.
* SAORestrictionArrayEqualityOp creates an equality operator
* for a single element of a scalar array constraint.
*/
static inline OpExpr *
static OpExpr *
SAORestrictionArrayEqualityOp(ScalarArrayOpExpr *arrayOperatorExpression,
Var *partitionColumn)
{
@ -1944,16 +1917,45 @@ SAORestrictionArrayEqualityOp(ScalarArrayOpExpr *arrayOperatorExpression,
/*
* Debug helper for logging expression nodes
* DebugLogNode is a helper for logging expression nodes.
*/
static inline void
static void
DebugLogNode(char *fmt, Node *node, List *deparseCtx)
{
if (!node)
if (node != NULL)
{
return;
char *deparsed = deparse_expression(node, deparseCtx, false, false);
ereport(DEBUG3, (errmsg(fmt, deparsed)));
}
char *deparsed = deparse_expression(node, deparseCtx, false, false);
ereport(DEBUG3, (errmsg(fmt, deparsed)));
}
/*
* DebugLogPruningInstance is a helper for logging purning constraints.
*/
static void
DebugLogPruningInstance(PruningInstance *pruning, List *deparseCtx)
{
DebugLogNode("constraint value: %s",
(Node *) pruning->equalConsts, deparseCtx);
DebugLogNode("constraint (lt) value: %s", \
(Node *) pruning->lessConsts, deparseCtx);
DebugLogNode("constraint (lteq) value: %s", \
(Node *) pruning->lessEqualConsts, deparseCtx);
DebugLogNode("constraint (gt) value: %s", \
(Node *) pruning->greaterConsts, deparseCtx);
DebugLogNode("constraint (gteq) value: %s",
(Node *) pruning->greaterEqualConsts, deparseCtx);
}
/*
* ConstraintCount returns how many arguments this node is taking.
*/
static int
ConstraintCount(PruningTreeNode *node)
{
return list_length(node->childBooleanNodes) +
list_length(node->validConstraints) +
(node->hasInvalidConstraints ? 1 : 0);
}

View File

@ -219,14 +219,14 @@ SET client_min_messages TO DEBUG3;
-- Check that we support runing for ANY/IN with literal.
SELECT count(*) FROM lineitem_hash_part
WHERE l_orderkey = ANY ('{1,2,3}');
DEBUG: constraint value: '1'::bigint COLLATE "default",
DEBUG: constraint value: '2'::bigint COLLATE "default",
DEBUG: constraint value: '3'::bigint COLLATE "default",
DEBUG: constraint value: '1'::bigint
DEBUG: constraint value: '2'::bigint
DEBUG: constraint value: '3'::bigint
DEBUG: shard count: 3
DEBUG: Router planner cannot handle multi-shard select queries
DEBUG: constraint value: '1'::bigint COLLATE "default",
DEBUG: constraint value: '2'::bigint COLLATE "default",
DEBUG: constraint value: '3'::bigint COLLATE "default",
DEBUG: constraint value: '1'::bigint
DEBUG: constraint value: '2'::bigint
DEBUG: constraint value: '3'::bigint
DEBUG: shard count: 3
DEBUG: assigned task to node localhost:xxxxx
DEBUG: assigned task to node localhost:xxxxx
@ -238,14 +238,14 @@ DEBUG: assigned task to node localhost:xxxxx
SELECT count(*) FROM lineitem_hash_part
WHERE l_orderkey IN (1,2,3);
DEBUG: constraint value: '1'::bigint COLLATE "default",
DEBUG: constraint value: '2'::bigint COLLATE "default",
DEBUG: constraint value: '3'::bigint COLLATE "default",
DEBUG: constraint value: '1'::bigint
DEBUG: constraint value: '2'::bigint
DEBUG: constraint value: '3'::bigint
DEBUG: shard count: 3
DEBUG: Router planner cannot handle multi-shard select queries
DEBUG: constraint value: '1'::bigint COLLATE "default",
DEBUG: constraint value: '2'::bigint COLLATE "default",
DEBUG: constraint value: '3'::bigint COLLATE "default",
DEBUG: constraint value: '1'::bigint
DEBUG: constraint value: '2'::bigint
DEBUG: constraint value: '3'::bigint
DEBUG: shard count: 3
DEBUG: assigned task to node localhost:xxxxx
DEBUG: assigned task to node localhost:xxxxx
@ -356,8 +356,8 @@ DEBUG: assigned task to node localhost:xxxxx
SELECT count(*) FROM lineitem
WHERE l_orderkey >= 1 AND l_orderkey <= 3;
DEBUG: Router planner does not support append-partitioned tables.
DEBUG: constraint (lteq) value: '3'::bigint,
DEBUG: constraint (gteq) value: '1'::bigint,
DEBUG: constraint (lteq) value: '3'::bigint
DEBUG: constraint (gteq) value: '1'::bigint
DEBUG: shard count: 1
DEBUG: assigned task to node localhost:xxxxx
count
@ -368,8 +368,8 @@ DEBUG: assigned task to node localhost:xxxxx
SELECT count(*) FROM lineitem
WHERE (l_orderkey >= 1 AND l_orderkey <= 3) AND (l_quantity > 11 AND l_quantity < 22);
DEBUG: Router planner does not support append-partitioned tables.
DEBUG: constraint (lteq) value: '3'::bigint,
DEBUG: constraint (gteq) value: '1'::bigint,
DEBUG: constraint (lteq) value: '3'::bigint
DEBUG: constraint (gteq) value: '1'::bigint
DEBUG: shard count: 1
DEBUG: assigned task to node localhost:xxxxx
count
@ -381,9 +381,9 @@ DEBUG: assigned task to node localhost:xxxxx
SELECT count(*) FROM lineitem
WHERE l_orderkey = ANY ('{1,2,3}');
DEBUG: Router planner does not support append-partitioned tables.
DEBUG: constraint value: '1'::bigint COLLATE "default",
DEBUG: constraint value: '2'::bigint COLLATE "default",
DEBUG: constraint value: '3'::bigint COLLATE "default",
DEBUG: constraint value: '1'::bigint
DEBUG: constraint value: '2'::bigint
DEBUG: constraint value: '3'::bigint
DEBUG: shard count: 1
DEBUG: assigned task to node localhost:xxxxx
count
@ -394,9 +394,9 @@ DEBUG: assigned task to node localhost:xxxxx
SELECT count(*) FROM lineitem
WHERE l_orderkey IN (1,2,3);
DEBUG: Router planner does not support append-partitioned tables.
DEBUG: constraint value: '1'::bigint COLLATE "default",
DEBUG: constraint value: '2'::bigint COLLATE "default",
DEBUG: constraint value: '3'::bigint COLLATE "default",
DEBUG: constraint value: '1'::bigint
DEBUG: constraint value: '2'::bigint
DEBUG: constraint value: '3'::bigint
DEBUG: shard count: 1
DEBUG: assigned task to node localhost:xxxxx
count
@ -418,9 +418,9 @@ DEBUG: assigned task to node localhost:xxxxx
SELECT count(*) FROM lineitem_range
WHERE l_orderkey = ANY ('{1,2,3}');
DEBUG: constraint value: '1'::bigint COLLATE "default",
DEBUG: constraint value: '2'::bigint COLLATE "default",
DEBUG: constraint value: '3'::bigint COLLATE "default",
DEBUG: constraint value: '1'::bigint
DEBUG: constraint value: '2'::bigint
DEBUG: constraint value: '3'::bigint
DEBUG: shard count: 1
DEBUG: Creating router plan
DEBUG: Plan is router executable
@ -431,9 +431,9 @@ DEBUG: Plan is router executable
SELECT count(*) FROM lineitem_range
WHERE l_orderkey IN (1,2,3);
DEBUG: constraint value: '1'::bigint COLLATE "default",
DEBUG: constraint value: '2'::bigint COLLATE "default",
DEBUG: constraint value: '3'::bigint COLLATE "default",
DEBUG: constraint value: '1'::bigint
DEBUG: constraint value: '2'::bigint
DEBUG: constraint value: '3'::bigint
DEBUG: shard count: 1
DEBUG: Creating router plan
DEBUG: Plan is router executable
@ -526,7 +526,7 @@ DEBUG: assigned task to node localhost:xxxxx
SELECT count(*) FROM orders_hash_partitioned
WHERE o_orderkey = (random() + 100) AND o_orderkey = 1;
DEBUG: constraint value: 1,
DEBUG: constraint value: 1
DEBUG: shard count: 1
DEBUG: Creating router plan
DEBUG: Plan is router executable
@ -575,9 +575,9 @@ SELECT count(*)
WHERE orders1.o_orderkey = orders2.o_orderkey
AND orders1.o_orderkey = 1
AND orders2.o_orderkey is NULL;
DEBUG: constraint value: 1,
DEBUG: constraint value: 1
DEBUG: shard count: 1
DEBUG: constraint value: 1,
DEBUG: constraint value: 1
DEBUG: shard count: 1
DEBUG: Creating router plan
DEBUG: Plan is router executable
@ -606,7 +606,7 @@ DEBUG: assigned task to node localhost:xxxxx
-- Shards restricted correctly with prunable constraint
SELECT count(*) FROM orders_hash_partitioned
WHERE o_orderkey = 1;
DEBUG: constraint value: 1,
DEBUG: constraint value: 1
DEBUG: shard count: 1
DEBUG: Creating router plan
DEBUG: Plan is router executable
@ -619,7 +619,7 @@ DETAIL: distribution column value: 1
-- Shards restricted correctly with prunable constraint ANDed with unprunable expression using OR
SELECT count(*) FROM orders_hash_partitioned
WHERE o_orderkey = 1 AND (o_custkey = 11 OR o_custkey = 22);
DEBUG: constraint value: 1,
DEBUG: constraint value: 1
DEBUG: shard count: 1
DEBUG: Creating router plan
DEBUG: Plan is router executable
@ -632,12 +632,12 @@ DETAIL: distribution column value: 1
-- Shards restricted correctly with prunable constraints ORed
SELECT count(*) FROM orders_hash_partitioned
WHERE (o_orderkey = 1 OR o_orderkey = 2);
DEBUG: constraint value: 1,
DEBUG: constraint value: 2,
DEBUG: constraint value: 1
DEBUG: constraint value: 2
DEBUG: shard count: 2
DEBUG: Router planner cannot handle multi-shard select queries
DEBUG: constraint value: 1,
DEBUG: constraint value: 2,
DEBUG: constraint value: 1
DEBUG: constraint value: 2
DEBUG: shard count: 2
DEBUG: assigned task to node localhost:xxxxx
DEBUG: assigned task to node localhost:xxxxx
@ -649,12 +649,12 @@ DEBUG: assigned task to node localhost:xxxxx
-- Shards restricted correctly with prunable constraints ANDed with unprunable expression using OR
SELECT count(*) FROM orders_hash_partitioned
WHERE (o_orderkey = 1 OR o_orderkey = 2) AND (o_custkey = 11 OR o_custkey = 22);
DEBUG: constraint value: 1,
DEBUG: constraint value: 2,
DEBUG: constraint value: 1
DEBUG: constraint value: 2
DEBUG: shard count: 2
DEBUG: Router planner cannot handle multi-shard select queries
DEBUG: constraint value: 1,
DEBUG: constraint value: 2,
DEBUG: constraint value: 1
DEBUG: constraint value: 2
DEBUG: shard count: 2
DEBUG: assigned task to node localhost:xxxxx
DEBUG: assigned task to node localhost:xxxxx
@ -666,16 +666,16 @@ DEBUG: assigned task to node localhost:xxxxx
-- Shards restricted correctly with many different prunable constraints ORed
SELECT count(*) FROM orders_hash_partitioned
WHERE (o_orderkey = 1 AND o_custkey = 11) OR (o_orderkey = 1 AND o_custkey = 33) OR (o_orderkey = 2 AND o_custkey = 22) OR (o_orderkey = 2 AND o_custkey = 44);
DEBUG: constraint value: 1,
DEBUG: constraint value: 1,
DEBUG: constraint value: 2,
DEBUG: constraint value: 2,
DEBUG: constraint value: 1
DEBUG: constraint value: 1
DEBUG: constraint value: 2
DEBUG: constraint value: 2
DEBUG: shard count: 2
DEBUG: Router planner cannot handle multi-shard select queries
DEBUG: constraint value: 1,
DEBUG: constraint value: 1,
DEBUG: constraint value: 2,
DEBUG: constraint value: 2,
DEBUG: constraint value: 1
DEBUG: constraint value: 1
DEBUG: constraint value: 2
DEBUG: constraint value: 2
DEBUG: shard count: 2
DEBUG: assigned task to node localhost:xxxxx
DEBUG: assigned task to node localhost:xxxxx
@ -687,12 +687,12 @@ DEBUG: assigned task to node localhost:xxxxx
-- Shards restricted correctly with prunable SAO constraint ANDed with unprunable expression using OR
SELECT count(*) FROM orders_hash_partitioned
WHERE (o_orderkey IN (1,2)) AND (o_custkey = 11 OR o_custkey = 22 OR o_custkey = 33);
DEBUG: constraint value: 1 COLLATE "default",
DEBUG: constraint value: 2 COLLATE "default",
DEBUG: constraint value: 1
DEBUG: constraint value: 2
DEBUG: shard count: 2
DEBUG: Router planner cannot handle multi-shard select queries
DEBUG: constraint value: 1 COLLATE "default",
DEBUG: constraint value: 2 COLLATE "default",
DEBUG: constraint value: 1
DEBUG: constraint value: 2
DEBUG: shard count: 2
DEBUG: assigned task to node localhost:xxxxx
DEBUG: assigned task to node localhost:xxxxx
@ -704,12 +704,12 @@ DEBUG: assigned task to node localhost:xxxxx
-- Shards restricted correctly with prunable SAO constraint ANDed with multiple unprunable expressions
SELECT count(*) FROM orders_hash_partitioned
WHERE (o_orderkey IN (1,2)) AND (o_totalprice < 11 OR o_totalprice > 19) AND o_shippriority > 100 AND (o_custkey = 11 OR o_custkey = 22);
DEBUG: constraint value: 1 COLLATE "default",
DEBUG: constraint value: 2 COLLATE "default",
DEBUG: constraint value: 1
DEBUG: constraint value: 2
DEBUG: shard count: 2
DEBUG: Router planner cannot handle multi-shard select queries
DEBUG: constraint value: 1 COLLATE "default",
DEBUG: constraint value: 2 COLLATE "default",
DEBUG: constraint value: 1
DEBUG: constraint value: 2
DEBUG: shard count: 2
DEBUG: assigned task to node localhost:xxxxx
DEBUG: assigned task to node localhost:xxxxx
@ -721,16 +721,16 @@ DEBUG: assigned task to node localhost:xxxxx
-- Shards restricted correctly with prunable SAO constraints ORed
SELECT count(*) FROM orders_hash_partitioned
WHERE (o_orderkey IN (1,2) AND o_custkey = 11) OR (o_orderkey IN (2,3) AND o_custkey = 22);
DEBUG: constraint value: 1 COLLATE "default",
DEBUG: constraint value: 2 COLLATE "default",
DEBUG: constraint value: 2 COLLATE "default",
DEBUG: constraint value: 3 COLLATE "default",
DEBUG: constraint value: 1
DEBUG: constraint value: 2
DEBUG: constraint value: 2
DEBUG: constraint value: 3
DEBUG: shard count: 3
DEBUG: Router planner cannot handle multi-shard select queries
DEBUG: constraint value: 1 COLLATE "default",
DEBUG: constraint value: 2 COLLATE "default",
DEBUG: constraint value: 2 COLLATE "default",
DEBUG: constraint value: 3 COLLATE "default",
DEBUG: constraint value: 1
DEBUG: constraint value: 2
DEBUG: constraint value: 2
DEBUG: constraint value: 3
DEBUG: shard count: 3
DEBUG: assigned task to node localhost:xxxxx
DEBUG: assigned task to node localhost:xxxxx
@ -760,14 +760,14 @@ DEBUG: assigned task to node localhost:xxxxx
-- Shards restricted correctly with prunable constraint ORed
SELECT count(*) FROM orders_hash_partitioned
WHERE o_orderkey = 1 OR ((o_orderkey = 2 AND o_custkey = 22) OR (o_orderkey = 3 AND o_custkey = 33));
DEBUG: constraint value: 1,
DEBUG: constraint value: 2,
DEBUG: constraint value: 3,
DEBUG: constraint value: 1
DEBUG: constraint value: 2
DEBUG: constraint value: 3
DEBUG: shard count: 3
DEBUG: Router planner cannot handle multi-shard select queries
DEBUG: constraint value: 1,
DEBUG: constraint value: 2,
DEBUG: constraint value: 3,
DEBUG: constraint value: 1
DEBUG: constraint value: 2
DEBUG: constraint value: 3
DEBUG: shard count: 3
DEBUG: assigned task to node localhost:xxxxx
DEBUG: assigned task to node localhost:xxxxx
@ -780,12 +780,12 @@ DEBUG: assigned task to node localhost:xxxxx
-- Shards restricted correctly with prunable constraint ORed with falsy expression
SELECT count(*) FROM orders_hash_partitioned
WHERE o_orderkey = 1 OR (o_orderkey = 2 AND (o_custkey = 11 OR (o_orderkey = 3 AND o_custkey = 44)));
DEBUG: constraint value: 1,
DEBUG: constraint value: 2,
DEBUG: constraint value: 1
DEBUG: constraint value: 2
DEBUG: shard count: 2
DEBUG: Router planner cannot handle multi-shard select queries
DEBUG: constraint value: 1,
DEBUG: constraint value: 2,
DEBUG: constraint value: 1
DEBUG: constraint value: 2
DEBUG: shard count: 2
DEBUG: assigned task to node localhost:xxxxx
DEBUG: assigned task to node localhost:xxxxx
@ -797,12 +797,12 @@ DEBUG: assigned task to node localhost:xxxxx
-- Shards restricted correctly with prunable SAO constraint ORed with prunable nested EQ constraint
SELECT count(*) FROM orders_hash_partitioned
WHERE (o_orderkey IN (1,2)) AND (o_custkey = 11 OR o_custkey = 22 OR o_custkey = 33) AND o_totalprice <= 20;
DEBUG: constraint value: 1 COLLATE "default",
DEBUG: constraint value: 2 COLLATE "default",
DEBUG: constraint value: 1
DEBUG: constraint value: 2
DEBUG: shard count: 2
DEBUG: Router planner cannot handle multi-shard select queries
DEBUG: constraint value: 1 COLLATE "default",
DEBUG: constraint value: 2 COLLATE "default",
DEBUG: constraint value: 1
DEBUG: constraint value: 2
DEBUG: shard count: 2
DEBUG: assigned task to node localhost:xxxxx
DEBUG: assigned task to node localhost:xxxxx
@ -814,12 +814,12 @@ DEBUG: assigned task to node localhost:xxxxx
-- Shards restricted correctly with prunable SAO constraint ANDed with unprunable expressions
SELECT count(*) FROM orders_hash_partitioned
WHERE (o_orderkey IN (1,2)) AND (o_custkey = 11 OR o_custkey = 33) AND o_custkey = 22;
DEBUG: constraint value: 1 COLLATE "default",
DEBUG: constraint value: 2 COLLATE "default",
DEBUG: constraint value: 1
DEBUG: constraint value: 2
DEBUG: shard count: 2
DEBUG: Router planner cannot handle multi-shard select queries
DEBUG: constraint value: 1 COLLATE "default",
DEBUG: constraint value: 2 COLLATE "default",
DEBUG: constraint value: 1
DEBUG: constraint value: 2
DEBUG: shard count: 2
DEBUG: assigned task to node localhost:xxxxx
DEBUG: assigned task to node localhost:xxxxx
@ -848,14 +848,14 @@ DEBUG: assigned task to node localhost:xxxxx
-- Shards restricted correctly with prunable SAO constraint ORed with prunable nested EQ constraint
SELECT count(*) FROM orders_hash_partitioned
WHERE ((o_orderkey IN (1,2)) AND (o_custkey = 11 OR o_custkey = 22)) OR (o_orderkey = 3 AND o_custkey = 33);
DEBUG: constraint value: 3,
DEBUG: constraint value: 1 COLLATE "default",
DEBUG: constraint value: 2 COLLATE "default",
DEBUG: constraint value: 3
DEBUG: constraint value: 1
DEBUG: constraint value: 2
DEBUG: shard count: 3
DEBUG: Router planner cannot handle multi-shard select queries
DEBUG: constraint value: 3,
DEBUG: constraint value: 1 COLLATE "default",
DEBUG: constraint value: 2 COLLATE "default",
DEBUG: constraint value: 3
DEBUG: constraint value: 1
DEBUG: constraint value: 2
DEBUG: shard count: 3
DEBUG: assigned task to node localhost:xxxxx
DEBUG: assigned task to node localhost:xxxxx
@ -885,7 +885,7 @@ DEBUG: assigned task to node localhost:xxxxx
-- Single shard used when deeply nested prunable expression is restrictive with nested ANDs
SELECT count(*) FROM orders_hash_partitioned
WHERE o_orderkey = 1 OR (o_orderkey = 2 AND (o_orderkey = 3 OR (o_orderkey = 1 AND o_custkey = 11)));
DEBUG: constraint value: 1,
DEBUG: constraint value: 1
DEBUG: shard count: 1
DEBUG: Creating router plan
DEBUG: Plan is router executable
@ -910,14 +910,14 @@ DETAIL: distribution column value: 1
-- Deeply nested prunable expression affects used shards
SELECT count(*) FROM orders_hash_partitioned
WHERE o_orderkey = 1 OR ((o_orderkey = 2 OR o_orderkey = 3) AND (o_custkey = 22 OR o_custkey = 33));
DEBUG: constraint value: 1,
DEBUG: constraint value: 2,
DEBUG: constraint value: 3,
DEBUG: constraint value: 1
DEBUG: constraint value: 2
DEBUG: constraint value: 3
DEBUG: shard count: 3
DEBUG: Router planner cannot handle multi-shard select queries
DEBUG: constraint value: 1,
DEBUG: constraint value: 2,
DEBUG: constraint value: 3,
DEBUG: constraint value: 1
DEBUG: constraint value: 2
DEBUG: constraint value: 3
DEBUG: shard count: 3
DEBUG: assigned task to node localhost:xxxxx
DEBUG: assigned task to node localhost:xxxxx