Refactor creating a basic ClauseWalkerContext into CreateBasicClauseWalkerContext

pull/4753/head
Onur Tirtir 2021-02-27 00:32:59 +03:00
parent a114bf141e
commit 29641f9ef2
2 changed files with 105 additions and 68 deletions

View File

@ -138,17 +138,6 @@ typedef struct PendingPruningInstance
PruningTreeNode *continueAt; PruningTreeNode *continueAt;
} PendingPruningInstance; } PendingPruningInstance;
#if PG_VERSION_NUM >= PG_VERSION_12
typedef union \
{ \
FunctionCallInfoBaseData fcinfo; \
/* ensure enough space for nargs args is available */ \
char fcinfo_data[SizeForFunctionCallInfo(2)]; \
} FunctionCall2InfoData;
#else
typedef FunctionCallInfoData FunctionCall2InfoData;
#endif
/* /*
* We also ignore this warning in ./configure, but that's not always enough. * We also ignore this warning in ./configure, but that's not always enough.
* The flags that are used during compilation by ./configure are determined by * The flags that are used during compilation by ./configure are determined by
@ -172,7 +161,6 @@ typedef FunctionCallInfoData FunctionCall2InfoData;
typedef struct ClauseWalkerContext typedef struct ClauseWalkerContext
{ {
Var *partitionColumn; Var *partitionColumn;
char partitionMethod;
/* ORed list of pruning targets */ /* ORed list of pruning targets */
List *pruningInstances; List *pruningInstances;
@ -192,9 +180,11 @@ typedef struct ClauseWalkerContext
* cheaper. * cheaper.
*/ */
FunctionCall2InfoData compareValueFunctionCall; FunctionCall2InfoData compareValueFunctionCall;
FunctionCall2InfoData compareIntervalFunctionCall;
} ClauseWalkerContext; } ClauseWalkerContext;
static ClauseWalkerContext * CreateClauseWalkerContext(Var *column, List *whereClauseList,
FunctionCall2InfoData *
compareValueFunctionCall);
static bool BuildPruningTree(Node *node, PruningTreeBuildContext *context); static bool BuildPruningTree(Node *node, PruningTreeBuildContext *context);
static void SimplifyPruningTree(PruningTreeNode *node, PruningTreeNode *parent); static void SimplifyPruningTree(PruningTreeNode *node, PruningTreeNode *parent);
static void PrunableExpressions(PruningTreeNode *node, ClauseWalkerContext *context); static void PrunableExpressions(PruningTreeNode *node, ClauseWalkerContext *context);
@ -223,17 +213,18 @@ static int PerformValueCompare(FunctionCallInfo compareFunctionCall, Datum a,
Datum b); Datum b);
static int PerformCompare(FunctionCallInfo compareFunctionCall); static int PerformCompare(FunctionCallInfo compareFunctionCall);
static List * PruneOne(CitusTableCacheEntry *cacheEntry, ClauseWalkerContext *context, static List * PruneOne(CitusTableCacheEntry *cacheEntry, PruningInstance *prune,
PruningInstance *prune); FunctionCall2InfoData *compareIntervalFunctionCall,
char partitionMethod);
static List * PruneWithBoundaries(CitusTableCacheEntry *cacheEntry, static List * PruneWithBoundaries(CitusTableCacheEntry *cacheEntry,
ClauseWalkerContext *context, PruningInstance *prune,
PruningInstance *prune); FunctionCall2InfoData *compareIntervalFunctionCall);
static List * ExhaustivePrune(CitusTableCacheEntry *cacheEntry, static List * ExhaustivePrune(CitusTableCacheEntry *cacheEntry,
ClauseWalkerContext *context, PruningInstance *prune,
PruningInstance *prune); FunctionCall2InfoData *compareIntervalFunctionCall);
static bool ExhaustivePruneOne(ShardInterval *curInterval, static bool ExhaustivePruneOne(ShardInterval *curInterval,
ClauseWalkerContext *context, PruningInstance *prune,
PruningInstance *prune); FunctionCall2InfoData *compareIntervalFunctionCall);
static int UpperShardBoundary(Datum partitionColumnValue, static int UpperShardBoundary(Datum partitionColumnValue,
ShardInterval **shardIntervalCache, ShardInterval **shardIntervalCache,
int shardCount, FunctionCallInfo compareFunction, int shardCount, FunctionCallInfo compareFunction,
@ -267,7 +258,6 @@ PruneShards(Oid relationId, Index rangeTableId, List *whereClauseList,
CitusTableCacheEntry *cacheEntry = GetCitusTableCacheEntry(relationId); CitusTableCacheEntry *cacheEntry = GetCitusTableCacheEntry(relationId);
int shardCount = cacheEntry->shardIntervalArrayLength; int shardCount = cacheEntry->shardIntervalArrayLength;
char partitionMethod = cacheEntry->partitionMethod; char partitionMethod = cacheEntry->partitionMethod;
ClauseWalkerContext context = { 0 };
ListCell *pruneCell; ListCell *pruneCell;
List *prunedList = NIL; List *prunedList = NIL;
bool foundRestriction = false; bool foundRestriction = false;
@ -294,16 +284,11 @@ PruneShards(Oid relationId, Index rangeTableId, List *whereClauseList,
return DeepCopyShardIntervalList(prunedList); return DeepCopyShardIntervalList(prunedList);
} }
FunctionCall2InfoData compareIntervalFunctionCall;
context.partitionMethod = partitionMethod;
context.partitionColumn = PartitionColumn(relationId, rangeTableId);
context.currentPruningInstance = palloc0(sizeof(PruningInstance));
if (cacheEntry->shardIntervalCompareFunction) if (cacheEntry->shardIntervalCompareFunction)
{ {
/* initiate function call info once (allows comparators to cache metadata) */ /* initiate function call info once (allows comparators to cache metadata) */
InitFunctionCallInfoData(*(FunctionCallInfo) & InitFunctionCallInfoData(*(FunctionCallInfo) & compareIntervalFunctionCall,
context.compareIntervalFunctionCall,
cacheEntry->shardIntervalCompareFunction, cacheEntry->shardIntervalCompareFunction,
2, cacheEntry->partitionColumn->varcollid, NULL, NULL); 2, cacheEntry->partitionColumn->varcollid, NULL, NULL);
} }
@ -313,11 +298,11 @@ PruneShards(Oid relationId, Index rangeTableId, List *whereClauseList,
"a shard interval comparator"))); "a shard interval comparator")));
} }
FunctionCall2InfoData compareValueFunctionCall;
if (cacheEntry->shardColumnCompareFunction) if (cacheEntry->shardColumnCompareFunction)
{ {
/* initiate function call info once (allows comparators to cache metadata) */ /* initiate function call info once (allows comparators to cache metadata) */
InitFunctionCallInfoData(*(FunctionCallInfo) & InitFunctionCallInfoData(*(FunctionCallInfo) & compareValueFunctionCall,
context.compareValueFunctionCall,
cacheEntry->shardColumnCompareFunction, cacheEntry->shardColumnCompareFunction,
2, cacheEntry->partitionColumn->varcollid, NULL, NULL); 2, cacheEntry->partitionColumn->varcollid, NULL, NULL);
} }
@ -327,28 +312,18 @@ PruneShards(Oid relationId, Index rangeTableId, List *whereClauseList,
"a partition column comparator"))); "a partition column comparator")));
} }
PruningTreeNode *tree = CreatePruningNode(AND_EXPR);
PruningTreeBuildContext treeBuildContext = { 0 };
treeBuildContext.current = tree;
treeBuildContext.partitionColumn = PartitionColumn(relationId, rangeTableId);
/* Build logical tree of prunable restrictions and invalid restrictions */
BuildPruningTree((Node *) whereClauseList, &treeBuildContext);
/* Simplify logic tree of prunable restrictions */
SimplifyPruningTree(tree, NULL);
/* Figure out what we can prune on */
PrunableExpressions(tree, &context);
Var *partitionColumn = PartitionColumn(relationId, rangeTableId);
List *pruningInstanceList = BuildPruningInstanceList(partitionColumn,
whereClauseList,
&compareValueFunctionCall);
List *debugLoggedPruningInstances = NIL; List *debugLoggedPruningInstances = NIL;
/* /*
* Prune using each of the PrunableInstances we found, and OR results * Prune using each of the PrunableInstances we found, and OR results
* together. * together.
*/ */
foreach(pruneCell, context.pruningInstances) foreach(pruneCell, pruningInstanceList)
{ {
PruningInstance *prune = (PruningInstance *) lfirst(pruneCell); PruningInstance *prune = (PruningInstance *) lfirst(pruneCell);
@ -371,7 +346,7 @@ PruneShards(Oid relationId, Index rangeTableId, List *whereClauseList,
break; break;
} }
if (context.partitionMethod == DISTRIBUTE_BY_HASH) if (partitionMethod == DISTRIBUTE_BY_HASH)
{ {
if (!prune->evaluatesToFalse && !prune->equalConsts && if (!prune->evaluatesToFalse && !prune->equalConsts &&
!prune->hashedEqualConsts) !prune->hashedEqualConsts)
@ -400,7 +375,9 @@ PruneShards(Oid relationId, Index rangeTableId, List *whereClauseList,
} }
} }
List *pruneOneList = PruneOne(cacheEntry, &context, prune); List *pruneOneList = PruneOne(cacheEntry, prune,
&compareIntervalFunctionCall,
partitionMethod);
if (prunedList) if (prunedList)
{ {
@ -475,6 +452,53 @@ PruneShards(Oid relationId, Index rangeTableId, List *whereClauseList,
} }
/*
* BuildPruningInstanceList builds and returns a list of prune instances for
* given column by using given from given where clause list and function call
* object.
*/
List *
BuildPruningInstanceList(Var *column, List *whereClauseList,
FunctionCall2InfoData *compareValueFunctionCall)
{
PruningTreeNode *tree = CreatePruningNode(AND_EXPR);
PruningTreeBuildContext *treeBuildContext = palloc0(sizeof(PruningTreeBuildContext));
treeBuildContext->current = tree;
treeBuildContext->partitionColumn = column;
/* Build logical tree of prunable restrictions and invalid restrictions */
BuildPruningTree((Node *) whereClauseList, treeBuildContext);
/* Simplify logic tree of prunable restrictions */
SimplifyPruningTree(tree, NULL);
ClauseWalkerContext *clauseWalkerContext =
CreateClauseWalkerContext(column, whereClauseList, compareValueFunctionCall);
/* Figure out what we can prune on */
PrunableExpressions(tree, clauseWalkerContext);
return clauseWalkerContext->pruningInstances;
}
/*
* CreateClauseWalkerContext creates a ClauseWalkerContext object initialized
* by given arguments.
*/
static ClauseWalkerContext *
CreateClauseWalkerContext(Var *column, List *whereClauseList,
FunctionCall2InfoData *compareValueFunctionCall)
{
ClauseWalkerContext *clauseWalkerContext = palloc0(sizeof(ClauseWalkerContext));
clauseWalkerContext->partitionColumn = column;
clauseWalkerContext->currentPruningInstance = palloc0(sizeof(PruningInstance));
clauseWalkerContext->compareValueFunctionCall = *compareValueFunctionCall;
return clauseWalkerContext;
}
/* /*
* IsValidConditionNode checks whether node is a valid constraint for pruning. * IsValidConditionNode checks whether node is a valid constraint for pruning.
*/ */
@ -1360,8 +1384,8 @@ DeepCopyShardIntervalList(List *originalShardIntervalList)
* PruningInstance. * PruningInstance.
*/ */
static List * static List *
PruneOne(CitusTableCacheEntry *cacheEntry, ClauseWalkerContext *context, PruneOne(CitusTableCacheEntry *cacheEntry, PruningInstance *prune,
PruningInstance *prune) FunctionCall2InfoData *compareIntervalFunctionCall, char partitionMethod)
{ {
ShardInterval *shardInterval = NULL; ShardInterval *shardInterval = NULL;
@ -1401,7 +1425,7 @@ PruneOne(CitusTableCacheEntry *cacheEntry, ClauseWalkerContext *context,
{ {
ShardInterval **sortedShardIntervalArray = cacheEntry->sortedShardIntervalArray; ShardInterval **sortedShardIntervalArray = cacheEntry->sortedShardIntervalArray;
Assert(context->partitionMethod == DISTRIBUTE_BY_HASH); Assert(partitionMethod == DISTRIBUTE_BY_HASH);
int shardIndex = FindShardIntervalIndex(prune->hashedEqualConsts->constvalue, int shardIndex = FindShardIntervalIndex(prune->hashedEqualConsts->constvalue,
cacheEntry); cacheEntry);
@ -1438,8 +1462,9 @@ PruneOne(CitusTableCacheEntry *cacheEntry, ClauseWalkerContext *context,
*/ */
if (shardInterval) if (shardInterval)
{ {
if (context->partitionMethod != DISTRIBUTE_BY_HASH && if (partitionMethod != DISTRIBUTE_BY_HASH &&
ExhaustivePruneOne(shardInterval, context, prune)) ExhaustivePruneOne(shardInterval, prune,
compareIntervalFunctionCall))
{ {
return NIL; return NIL;
} }
@ -1454,7 +1479,7 @@ PruneOne(CitusTableCacheEntry *cacheEntry, ClauseWalkerContext *context,
* Should never get here for hashing, we've filtered down to either zero * Should never get here for hashing, we've filtered down to either zero
* or one shard, and returned. * or one shard, and returned.
*/ */
Assert(context->partitionMethod != DISTRIBUTE_BY_HASH); Assert(partitionMethod != DISTRIBUTE_BY_HASH);
/* /*
* Next method: binary search with fuzzy boundaries. Can't trivially do so * Next method: binary search with fuzzy boundaries. Can't trivially do so
@ -1467,13 +1492,14 @@ PruneOne(CitusTableCacheEntry *cacheEntry, ClauseWalkerContext *context,
prune->greaterConsts || prune->greaterEqualConsts || prune->greaterConsts || prune->greaterEqualConsts ||
prune->lessConsts || prune->lessEqualConsts)) prune->lessConsts || prune->lessEqualConsts))
{ {
return PruneWithBoundaries(cacheEntry, context, prune); return PruneWithBoundaries(cacheEntry, prune,
compareIntervalFunctionCall);
} }
/* /*
* Brute force: Check each shard. * Brute force: Check each shard.
*/ */
return ExhaustivePrune(cacheEntry, context, prune); return ExhaustivePrune(cacheEntry, prune, compareIntervalFunctionCall);
} }
@ -1667,8 +1693,8 @@ UpperShardBoundary(Datum partitionColumnValue, ShardInterval **shardIntervalCach
* list of surviving shards. * list of surviving shards.
*/ */
static List * static List *
PruneWithBoundaries(CitusTableCacheEntry *cacheEntry, ClauseWalkerContext *context, PruneWithBoundaries(CitusTableCacheEntry *cacheEntry, PruningInstance *prune,
PruningInstance *prune) FunctionCall2InfoData *compareIntervalFunctionCall)
{ {
List *remainingShardList = NIL; List *remainingShardList = NIL;
int shardCount = cacheEntry->shardIntervalArrayLength; int shardCount = cacheEntry->shardIntervalArrayLength;
@ -1681,8 +1707,7 @@ PruneWithBoundaries(CitusTableCacheEntry *cacheEntry, ClauseWalkerContext *conte
bool upperBoundInclusive = false; bool upperBoundInclusive = false;
int lowerBoundIdx = -1; int lowerBoundIdx = -1;
int upperBoundIdx = -1; int upperBoundIdx = -1;
FunctionCallInfo compareFunctionCall = (FunctionCallInfo) & FunctionCallInfo compareFunctionCall = (FunctionCallInfo) compareIntervalFunctionCall;
context->compareIntervalFunctionCall;
if (prune->greaterEqualConsts) if (prune->greaterEqualConsts)
{ {
@ -1782,8 +1807,8 @@ PruneWithBoundaries(CitusTableCacheEntry *cacheEntry, ClauseWalkerContext *conte
* constraints, by simply checking them for each individual shard. * constraints, by simply checking them for each individual shard.
*/ */
static List * static List *
ExhaustivePrune(CitusTableCacheEntry *cacheEntry, ClauseWalkerContext *context, ExhaustivePrune(CitusTableCacheEntry *cacheEntry, PruningInstance *prune,
PruningInstance *prune) FunctionCall2InfoData *compareIntervalFunctionCall)
{ {
List *remainingShardList = NIL; List *remainingShardList = NIL;
int shardCount = cacheEntry->shardIntervalArrayLength; int shardCount = cacheEntry->shardIntervalArrayLength;
@ -1793,7 +1818,7 @@ ExhaustivePrune(CitusTableCacheEntry *cacheEntry, ClauseWalkerContext *context,
{ {
ShardInterval *curInterval = sortedShardIntervalArray[curIdx]; ShardInterval *curInterval = sortedShardIntervalArray[curIdx];
if (!ExhaustivePruneOne(curInterval, context, prune)) if (!ExhaustivePruneOne(curInterval, prune, compareIntervalFunctionCall))
{ {
remainingShardList = lappend(remainingShardList, curInterval); remainingShardList = lappend(remainingShardList, curInterval);
} }
@ -1807,12 +1832,10 @@ ExhaustivePrune(CitusTableCacheEntry *cacheEntry, ClauseWalkerContext *context,
* ExhaustivePruneOne returns whether curInterval is pruned away. * ExhaustivePruneOne returns whether curInterval is pruned away.
*/ */
static bool static bool
ExhaustivePruneOne(ShardInterval *curInterval, ExhaustivePruneOne(ShardInterval *curInterval, PruningInstance *prune,
ClauseWalkerContext *context, FunctionCall2InfoData *compareIntervalFunctionCall)
PruningInstance *prune)
{ {
FunctionCallInfo compareFunctionCall = (FunctionCallInfo) & FunctionCallInfo compareFunctionCall = (FunctionCallInfo) compareIntervalFunctionCall;
context->compareIntervalFunctionCall;
/* NULL boundaries can't be compared to */ /* NULL boundaries can't be compared to */
if (!curInterval->minValueExists || !curInterval->maxValueExists) if (!curInterval->minValueExists || !curInterval->maxValueExists)

View File

@ -12,6 +12,7 @@
#define SHARD_PRUNING_H_ #define SHARD_PRUNING_H_
#include "distributed/metadata_cache.h" #include "distributed/metadata_cache.h"
#include "distributed/pg_version_constants.h"
#include "nodes/primnodes.h" #include "nodes/primnodes.h"
#define INVALID_SHARD_INDEX -1 #define INVALID_SHARD_INDEX -1
@ -65,6 +66,17 @@ typedef struct PruningInstance
bool isPartial; bool isPartial;
} PruningInstance; } PruningInstance;
#if PG_VERSION_NUM >= PG_VERSION_12
typedef union \
{ \
FunctionCallInfoBaseData fcinfo; \
/* ensure enough space for nargs args is available */ \
char fcinfo_data[SizeForFunctionCallInfo(2)]; \
} FunctionCall2InfoData;
#else
typedef FunctionCallInfoData FunctionCall2InfoData;
#endif
/* Function declarations for shard pruning */ /* Function declarations for shard pruning */
extern List * PruneShards(Oid relationId, Index rangeTableId, List *whereClauseList, extern List * PruneShards(Oid relationId, Index rangeTableId, List *whereClauseList,
Const **partitionValueConst); Const **partitionValueConst);
@ -77,5 +89,7 @@ bool VarConstOpExprClause(OpExpr *opClause, Var **varClause, Const **constantCla
extern bool ExhaustivePruneOneWithMinMax(PruningInstance *prune, extern bool ExhaustivePruneOneWithMinMax(PruningInstance *prune,
FunctionCallInfo compareFunctionCall, FunctionCallInfo compareFunctionCall,
Datum minimumValue, Datum maximumValue); Datum minimumValue, Datum maximumValue);
extern List * BuildPruningInstanceList(Var *column, List *whereClauseList,
FunctionCall2InfoData *compareValueFunctionCall);
#endif /* SHARD_PRUNING_H_ */ #endif /* SHARD_PRUNING_H_ */