mirror of https://github.com/citusdata/citus.git
Refactor creating a basic ClauseWalkerContext into CreateBasicClauseWalkerContext
parent
a114bf141e
commit
29641f9ef2
|
@ -138,17 +138,6 @@ typedef struct PendingPruningInstance
|
|||
PruningTreeNode *continueAt;
|
||||
} 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.
|
||||
* The flags that are used during compilation by ./configure are determined by
|
||||
|
@ -172,7 +161,6 @@ typedef FunctionCallInfoData FunctionCall2InfoData;
|
|||
typedef struct ClauseWalkerContext
|
||||
{
|
||||
Var *partitionColumn;
|
||||
char partitionMethod;
|
||||
|
||||
/* ORed list of pruning targets */
|
||||
List *pruningInstances;
|
||||
|
@ -192,9 +180,11 @@ typedef struct ClauseWalkerContext
|
|||
* cheaper.
|
||||
*/
|
||||
FunctionCall2InfoData compareValueFunctionCall;
|
||||
FunctionCall2InfoData compareIntervalFunctionCall;
|
||||
} ClauseWalkerContext;
|
||||
|
||||
static ClauseWalkerContext * CreateClauseWalkerContext(Var *column, List *whereClauseList,
|
||||
FunctionCall2InfoData *
|
||||
compareValueFunctionCall);
|
||||
static bool BuildPruningTree(Node *node, PruningTreeBuildContext *context);
|
||||
static void SimplifyPruningTree(PruningTreeNode *node, PruningTreeNode *parent);
|
||||
static void PrunableExpressions(PruningTreeNode *node, ClauseWalkerContext *context);
|
||||
|
@ -223,17 +213,18 @@ static int PerformValueCompare(FunctionCallInfo compareFunctionCall, Datum a,
|
|||
Datum b);
|
||||
static int PerformCompare(FunctionCallInfo compareFunctionCall);
|
||||
|
||||
static List * PruneOne(CitusTableCacheEntry *cacheEntry, ClauseWalkerContext *context,
|
||||
PruningInstance *prune);
|
||||
static List * PruneOne(CitusTableCacheEntry *cacheEntry, PruningInstance *prune,
|
||||
FunctionCall2InfoData *compareIntervalFunctionCall,
|
||||
char partitionMethod);
|
||||
static List * PruneWithBoundaries(CitusTableCacheEntry *cacheEntry,
|
||||
ClauseWalkerContext *context,
|
||||
PruningInstance *prune);
|
||||
PruningInstance *prune,
|
||||
FunctionCall2InfoData *compareIntervalFunctionCall);
|
||||
static List * ExhaustivePrune(CitusTableCacheEntry *cacheEntry,
|
||||
ClauseWalkerContext *context,
|
||||
PruningInstance *prune);
|
||||
PruningInstance *prune,
|
||||
FunctionCall2InfoData *compareIntervalFunctionCall);
|
||||
static bool ExhaustivePruneOne(ShardInterval *curInterval,
|
||||
ClauseWalkerContext *context,
|
||||
PruningInstance *prune);
|
||||
PruningInstance *prune,
|
||||
FunctionCall2InfoData *compareIntervalFunctionCall);
|
||||
static int UpperShardBoundary(Datum partitionColumnValue,
|
||||
ShardInterval **shardIntervalCache,
|
||||
int shardCount, FunctionCallInfo compareFunction,
|
||||
|
@ -267,7 +258,6 @@ PruneShards(Oid relationId, Index rangeTableId, List *whereClauseList,
|
|||
CitusTableCacheEntry *cacheEntry = GetCitusTableCacheEntry(relationId);
|
||||
int shardCount = cacheEntry->shardIntervalArrayLength;
|
||||
char partitionMethod = cacheEntry->partitionMethod;
|
||||
ClauseWalkerContext context = { 0 };
|
||||
ListCell *pruneCell;
|
||||
List *prunedList = NIL;
|
||||
bool foundRestriction = false;
|
||||
|
@ -294,16 +284,11 @@ PruneShards(Oid relationId, Index rangeTableId, List *whereClauseList,
|
|||
return DeepCopyShardIntervalList(prunedList);
|
||||
}
|
||||
|
||||
|
||||
context.partitionMethod = partitionMethod;
|
||||
context.partitionColumn = PartitionColumn(relationId, rangeTableId);
|
||||
context.currentPruningInstance = palloc0(sizeof(PruningInstance));
|
||||
|
||||
FunctionCall2InfoData compareIntervalFunctionCall;
|
||||
if (cacheEntry->shardIntervalCompareFunction)
|
||||
{
|
||||
/* initiate function call info once (allows comparators to cache metadata) */
|
||||
InitFunctionCallInfoData(*(FunctionCallInfo) &
|
||||
context.compareIntervalFunctionCall,
|
||||
InitFunctionCallInfoData(*(FunctionCallInfo) & compareIntervalFunctionCall,
|
||||
cacheEntry->shardIntervalCompareFunction,
|
||||
2, cacheEntry->partitionColumn->varcollid, NULL, NULL);
|
||||
}
|
||||
|
@ -313,11 +298,11 @@ PruneShards(Oid relationId, Index rangeTableId, List *whereClauseList,
|
|||
"a shard interval comparator")));
|
||||
}
|
||||
|
||||
FunctionCall2InfoData compareValueFunctionCall;
|
||||
if (cacheEntry->shardColumnCompareFunction)
|
||||
{
|
||||
/* initiate function call info once (allows comparators to cache metadata) */
|
||||
InitFunctionCallInfoData(*(FunctionCallInfo) &
|
||||
context.compareValueFunctionCall,
|
||||
InitFunctionCallInfoData(*(FunctionCallInfo) & compareValueFunctionCall,
|
||||
cacheEntry->shardColumnCompareFunction,
|
||||
2, cacheEntry->partitionColumn->varcollid, NULL, NULL);
|
||||
}
|
||||
|
@ -327,28 +312,18 @@ PruneShards(Oid relationId, Index rangeTableId, List *whereClauseList,
|
|||
"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;
|
||||
|
||||
/*
|
||||
* Prune using each of the PrunableInstances we found, and OR results
|
||||
* together.
|
||||
*/
|
||||
foreach(pruneCell, context.pruningInstances)
|
||||
foreach(pruneCell, pruningInstanceList)
|
||||
{
|
||||
PruningInstance *prune = (PruningInstance *) lfirst(pruneCell);
|
||||
|
||||
|
@ -371,7 +346,7 @@ PruneShards(Oid relationId, Index rangeTableId, List *whereClauseList,
|
|||
break;
|
||||
}
|
||||
|
||||
if (context.partitionMethod == DISTRIBUTE_BY_HASH)
|
||||
if (partitionMethod == DISTRIBUTE_BY_HASH)
|
||||
{
|
||||
if (!prune->evaluatesToFalse && !prune->equalConsts &&
|
||||
!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)
|
||||
{
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -1360,8 +1384,8 @@ DeepCopyShardIntervalList(List *originalShardIntervalList)
|
|||
* PruningInstance.
|
||||
*/
|
||||
static List *
|
||||
PruneOne(CitusTableCacheEntry *cacheEntry, ClauseWalkerContext *context,
|
||||
PruningInstance *prune)
|
||||
PruneOne(CitusTableCacheEntry *cacheEntry, PruningInstance *prune,
|
||||
FunctionCall2InfoData *compareIntervalFunctionCall, char partitionMethod)
|
||||
{
|
||||
ShardInterval *shardInterval = NULL;
|
||||
|
||||
|
@ -1401,7 +1425,7 @@ PruneOne(CitusTableCacheEntry *cacheEntry, ClauseWalkerContext *context,
|
|||
{
|
||||
ShardInterval **sortedShardIntervalArray = cacheEntry->sortedShardIntervalArray;
|
||||
|
||||
Assert(context->partitionMethod == DISTRIBUTE_BY_HASH);
|
||||
Assert(partitionMethod == DISTRIBUTE_BY_HASH);
|
||||
|
||||
int shardIndex = FindShardIntervalIndex(prune->hashedEqualConsts->constvalue,
|
||||
cacheEntry);
|
||||
|
@ -1438,8 +1462,9 @@ PruneOne(CitusTableCacheEntry *cacheEntry, ClauseWalkerContext *context,
|
|||
*/
|
||||
if (shardInterval)
|
||||
{
|
||||
if (context->partitionMethod != DISTRIBUTE_BY_HASH &&
|
||||
ExhaustivePruneOne(shardInterval, context, prune))
|
||||
if (partitionMethod != DISTRIBUTE_BY_HASH &&
|
||||
ExhaustivePruneOne(shardInterval, prune,
|
||||
compareIntervalFunctionCall))
|
||||
{
|
||||
return NIL;
|
||||
}
|
||||
|
@ -1454,7 +1479,7 @@ PruneOne(CitusTableCacheEntry *cacheEntry, ClauseWalkerContext *context,
|
|||
* Should never get here for hashing, we've filtered down to either zero
|
||||
* 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
|
||||
|
@ -1467,13 +1492,14 @@ PruneOne(CitusTableCacheEntry *cacheEntry, ClauseWalkerContext *context,
|
|||
prune->greaterConsts || prune->greaterEqualConsts ||
|
||||
prune->lessConsts || prune->lessEqualConsts))
|
||||
{
|
||||
return PruneWithBoundaries(cacheEntry, context, prune);
|
||||
return PruneWithBoundaries(cacheEntry, prune,
|
||||
compareIntervalFunctionCall);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
static List *
|
||||
PruneWithBoundaries(CitusTableCacheEntry *cacheEntry, ClauseWalkerContext *context,
|
||||
PruningInstance *prune)
|
||||
PruneWithBoundaries(CitusTableCacheEntry *cacheEntry, PruningInstance *prune,
|
||||
FunctionCall2InfoData *compareIntervalFunctionCall)
|
||||
{
|
||||
List *remainingShardList = NIL;
|
||||
int shardCount = cacheEntry->shardIntervalArrayLength;
|
||||
|
@ -1681,8 +1707,7 @@ PruneWithBoundaries(CitusTableCacheEntry *cacheEntry, ClauseWalkerContext *conte
|
|||
bool upperBoundInclusive = false;
|
||||
int lowerBoundIdx = -1;
|
||||
int upperBoundIdx = -1;
|
||||
FunctionCallInfo compareFunctionCall = (FunctionCallInfo) &
|
||||
context->compareIntervalFunctionCall;
|
||||
FunctionCallInfo compareFunctionCall = (FunctionCallInfo) compareIntervalFunctionCall;
|
||||
|
||||
if (prune->greaterEqualConsts)
|
||||
{
|
||||
|
@ -1782,8 +1807,8 @@ PruneWithBoundaries(CitusTableCacheEntry *cacheEntry, ClauseWalkerContext *conte
|
|||
* constraints, by simply checking them for each individual shard.
|
||||
*/
|
||||
static List *
|
||||
ExhaustivePrune(CitusTableCacheEntry *cacheEntry, ClauseWalkerContext *context,
|
||||
PruningInstance *prune)
|
||||
ExhaustivePrune(CitusTableCacheEntry *cacheEntry, PruningInstance *prune,
|
||||
FunctionCall2InfoData *compareIntervalFunctionCall)
|
||||
{
|
||||
List *remainingShardList = NIL;
|
||||
int shardCount = cacheEntry->shardIntervalArrayLength;
|
||||
|
@ -1793,7 +1818,7 @@ ExhaustivePrune(CitusTableCacheEntry *cacheEntry, ClauseWalkerContext *context,
|
|||
{
|
||||
ShardInterval *curInterval = sortedShardIntervalArray[curIdx];
|
||||
|
||||
if (!ExhaustivePruneOne(curInterval, context, prune))
|
||||
if (!ExhaustivePruneOne(curInterval, prune, compareIntervalFunctionCall))
|
||||
{
|
||||
remainingShardList = lappend(remainingShardList, curInterval);
|
||||
}
|
||||
|
@ -1807,12 +1832,10 @@ ExhaustivePrune(CitusTableCacheEntry *cacheEntry, ClauseWalkerContext *context,
|
|||
* ExhaustivePruneOne returns whether curInterval is pruned away.
|
||||
*/
|
||||
static bool
|
||||
ExhaustivePruneOne(ShardInterval *curInterval,
|
||||
ClauseWalkerContext *context,
|
||||
PruningInstance *prune)
|
||||
ExhaustivePruneOne(ShardInterval *curInterval, PruningInstance *prune,
|
||||
FunctionCall2InfoData *compareIntervalFunctionCall)
|
||||
{
|
||||
FunctionCallInfo compareFunctionCall = (FunctionCallInfo) &
|
||||
context->compareIntervalFunctionCall;
|
||||
FunctionCallInfo compareFunctionCall = (FunctionCallInfo) compareIntervalFunctionCall;
|
||||
|
||||
/* NULL boundaries can't be compared to */
|
||||
if (!curInterval->minValueExists || !curInterval->maxValueExists)
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#define SHARD_PRUNING_H_
|
||||
|
||||
#include "distributed/metadata_cache.h"
|
||||
#include "distributed/pg_version_constants.h"
|
||||
#include "nodes/primnodes.h"
|
||||
|
||||
#define INVALID_SHARD_INDEX -1
|
||||
|
@ -65,6 +66,17 @@ typedef struct PruningInstance
|
|||
bool isPartial;
|
||||
} 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 */
|
||||
extern List * PruneShards(Oid relationId, Index rangeTableId, List *whereClauseList,
|
||||
Const **partitionValueConst);
|
||||
|
@ -77,5 +89,7 @@ bool VarConstOpExprClause(OpExpr *opClause, Var **varClause, Const **constantCla
|
|||
extern bool ExhaustivePruneOneWithMinMax(PruningInstance *prune,
|
||||
FunctionCallInfo compareFunctionCall,
|
||||
Datum minimumValue, Datum maximumValue);
|
||||
extern List * BuildPruningInstanceList(Var *column, List *whereClauseList,
|
||||
FunctionCall2InfoData *compareValueFunctionCall);
|
||||
|
||||
#endif /* SHARD_PRUNING_H_ */
|
||||
|
|
Loading…
Reference in New Issue