Always return a dummy placement

fix-repartition-join-single-node
Jelte Fennema 2020-07-07 14:22:37 +02:00
parent 0b32a80f58
commit 4c3676feda
1 changed files with 44 additions and 23 deletions

View File

@ -156,6 +156,7 @@ static DeferredErrorMessage * MultiRouterPlannableQuery(Query *query);
static DeferredErrorMessage * ErrorIfQueryHasUnroutableModifyingCTE(Query *queryTree); static DeferredErrorMessage * ErrorIfQueryHasUnroutableModifyingCTE(Query *queryTree);
static bool SelectsFromDistributedTable(List *rangeTableList, Query *query); static bool SelectsFromDistributedTable(List *rangeTableList, Query *query);
static ShardPlacement * CreateDummyPlacement(bool hasLocalRelation); static ShardPlacement * CreateDummyPlacement(bool hasLocalRelation);
static ShardPlacement * CreateLocalDummyPlacement();
static List * get_all_actual_clauses(List *restrictinfo_list); static List * get_all_actual_clauses(List *restrictinfo_list);
static int CompareInsertValuesByShardId(const void *leftElement, static int CompareInsertValuesByShardId(const void *leftElement,
const void *rightElement); const void *rightElement);
@ -2233,6 +2234,25 @@ CreateTaskPlacementListForShardIntervals(List *shardIntervalListList, bool shard
} }
/*
* CreateLocalDummyPlacement creates a dummy placement for the local node that
* can be used for queries that don't involve any shards. The typical examples
* are:
* (a) queries that consist of only intermediate results
* (b) queries that hit zero shards (... WHERE false;)
*/
static ShardPlacement *
CreateLocalDummyPlacement()
{
ShardPlacement *dummyPlacement = CitusMakeNode(ShardPlacement);
dummyPlacement->nodeId = LOCAL_NODE_ID;
dummyPlacement->nodeName = LOCAL_HOST_NAME;
dummyPlacement->nodePort = PostPortNumber;
dummyPlacement->groupId = GetLocalGroupId();
return dummyPlacement;
}
/* /*
* CreateDummyPlacement creates a dummy placement that can be used for queries * CreateDummyPlacement creates a dummy placement that can be used for queries
* that don't involve any shards. The typical examples are: * that don't involve any shards. The typical examples are:
@ -2249,31 +2269,32 @@ static ShardPlacement *
CreateDummyPlacement(bool hasLocalRelation) CreateDummyPlacement(bool hasLocalRelation)
{ {
static uint32 zeroShardQueryRoundRobin = 0; static uint32 zeroShardQueryRoundRobin = 0;
ShardPlacement *dummyPlacement = CitusMakeNode(ShardPlacement);
if (TaskAssignmentPolicy == TASK_ASSIGNMENT_ROUND_ROBIN && !hasLocalRelation) if (TaskAssignmentPolicy != TASK_ASSIGNMENT_ROUND_ROBIN || hasLocalRelation)
{ {
return CreateLocalDummyPlacement();
}
List *workerNodeList = ActiveReadableWorkerNodeList(); List *workerNodeList = ActiveReadableWorkerNodeList();
if (workerNodeList == NIL) if (workerNodeList == NIL)
{ {
return NULL; /*
* We want to round-robin over the workers, but there are no workers.
* To make sure the query can still succeed we fall back to returning
* a local dummy placement.
*/
return CreateLocalDummyPlacement();
} }
int workerNodeCount = list_length(workerNodeList); int workerNodeCount = list_length(workerNodeList);
int workerNodeIndex = zeroShardQueryRoundRobin % workerNodeCount; int workerNodeIndex = zeroShardQueryRoundRobin % workerNodeCount;
WorkerNode *workerNode = (WorkerNode *) list_nth(workerNodeList, WorkerNode *workerNode = (WorkerNode *) list_nth(workerNodeList,
workerNodeIndex); workerNodeIndex);
ShardPlacement *dummyPlacement = CitusMakeNode(ShardPlacement);
SetPlacementNodeMetadata(dummyPlacement, workerNode); SetPlacementNodeMetadata(dummyPlacement, workerNode);
zeroShardQueryRoundRobin++; zeroShardQueryRoundRobin++;
}
else
{
dummyPlacement->nodeId = LOCAL_NODE_ID;
dummyPlacement->nodeName = LOCAL_HOST_NAME;
dummyPlacement->nodePort = PostPortNumber;
dummyPlacement->groupId = GetLocalGroupId();
}
return dummyPlacement; return dummyPlacement;
} }