mirror of https://github.com/citusdata/citus.git
Apply @mtuncer's reviews
parent
427af34719
commit
4c41096370
|
@ -32,7 +32,7 @@ static uint32 attributeEquivalenceId = 1;
|
|||
* relation attributes (i.e., not random expressions), we create an
|
||||
* AttributeEquivalenceClass to record this knowledge. If we later find another
|
||||
* equivalence B = C, we create another AttributeEquivalenceClass. Finally, we can
|
||||
* apply transitity rules and generate a new AttributeEquivalenceClass which includes
|
||||
* apply transitivity rules and generate a new AttributeEquivalenceClass which includes
|
||||
* A, B and C.
|
||||
*
|
||||
* Note that equality among the members are identified by the varattno and rteIdentity.
|
||||
|
@ -45,20 +45,20 @@ typedef struct AttributeEquivalenceClass
|
|||
|
||||
/*
|
||||
* AttributeEquivalenceClassMember - one member expression of an
|
||||
* AttributeEquivalenceClassMember. The important thing to consider is that
|
||||
* AttributeEquivalenceClass. The important thing to consider is that
|
||||
* the class member contains "rteIndentity" field. Note that each RTE_RELATION
|
||||
* is assigned a unique rteIdentity in AssignRTEIdentities() function.
|
||||
*
|
||||
* "varno" and "varattrno" is directly used from a Var clause that is being added
|
||||
* "varno" and "varattno" is directly used from a Var clause that is being added
|
||||
* to the attribute equivalence. Since we only use this class for relations, the member
|
||||
* also includes the relation id field.
|
||||
*/
|
||||
typedef struct AttributeEquivalenceClassMember
|
||||
{
|
||||
Oid relationId;
|
||||
int rteIdentity;
|
||||
Index varno;
|
||||
AttrNumber varattno;
|
||||
Oid relationId;
|
||||
int rteIdendity;
|
||||
} AttributeEquivalenceClassMember;
|
||||
|
||||
|
||||
|
@ -67,9 +67,9 @@ static List * GenerateAttributeEquivalencesForRelationRestrictions(
|
|||
RelationRestrictionContext *restrictionContext);
|
||||
static AttributeEquivalenceClass * AttributeEquivalenceClassForEquivalenceClass(
|
||||
EquivalenceClass *plannerEqClass, RelationRestriction *relationRestriction);
|
||||
static void AddToAttributeEquivalenceClass(PlannerInfo *root, Var *varToBeAdded,
|
||||
AttributeEquivalenceClass **
|
||||
attributeEquivalanceClass);
|
||||
static void AddToAttributeEquivalenceClass(AttributeEquivalenceClass **
|
||||
attributeEquivalanceClass,
|
||||
PlannerInfo *root, Var *varToBeAdded);
|
||||
static Var * GetVarFromAssignedParam(List *parentPlannerParamList,
|
||||
Param *plannerParam);
|
||||
static List * GenerateAttributeEquivalencesForJoinRestrictions(JoinRestrictionContext
|
||||
|
@ -78,9 +78,9 @@ static bool AttributeClassContainsAttributeClassMember(AttributeEquivalenceClass
|
|||
inputMember,
|
||||
AttributeEquivalenceClass *
|
||||
attributeEquivalenceClass);
|
||||
static List * AddAttributeClassToAttributeClassList(AttributeEquivalenceClass *
|
||||
attributeEquivalance,
|
||||
List *attributeEquivalenceList);
|
||||
static List * AddAttributeClassToAttributeClassList(List *attributeEquivalenceList,
|
||||
AttributeEquivalenceClass *
|
||||
attributeEquivalance);
|
||||
static AttributeEquivalenceClass * GenerateCommonEquivalence(List *
|
||||
attributeEquivalenceList);
|
||||
static void ListConcatUniqueAttributeClassMemberLists(AttributeEquivalenceClass **
|
||||
|
@ -94,6 +94,12 @@ static void ListConcatUniqueAttributeClassMemberLists(AttributeEquivalenceClass
|
|||
* RTE_RELATION follows the above rule, we can conclude that all RTE_RELATIONs are
|
||||
* joined on their partition keys.
|
||||
*
|
||||
* The function returns true if all relations are joined on their partition keys.
|
||||
* Otherwise, the function returns false. Since reference tables do not have partition
|
||||
* keys, we skip processing them. Also, if the query includes only a single non-reference
|
||||
* distributed relation, the function returns true since it doesn't make sense to check
|
||||
* for partition key equality in that case.
|
||||
*
|
||||
* In order to do that, we invented a new equivalence class namely:
|
||||
* AttributeEquivalenceClass. In very simple words, a AttributeEquivalenceClass is
|
||||
* identified by an unique id and consists of a list of AttributeEquivalenceMembers.
|
||||
|
@ -112,14 +118,15 @@ static void ListConcatUniqueAttributeClassMemberLists(AttributeEquivalenceClass
|
|||
* to find as much as information that Postgres planner provides to extensions. For the
|
||||
* details of the usage, please see GenerateAttributeEquivalencesForRelationRestrictions()
|
||||
* and GenerateAttributeEquivalencesForJoinRestrictions()
|
||||
*
|
||||
* Finally, as the name of the function reveals, the function returns true if all relations
|
||||
* are joined on their partition keys. Otherwise, the function returns false.
|
||||
*/
|
||||
bool
|
||||
AllRelationsJoinedOnPartitionKey(RelationRestrictionContext *restrictionContext,
|
||||
JoinRestrictionContext *joinRestrictionContext)
|
||||
AllRelationsJoinedOnPartitionKey(PlannerRestrictionContext *plannerRestrictionContext)
|
||||
{
|
||||
RelationRestrictionContext *restrictionContext =
|
||||
plannerRestrictionContext->relationRestrictionContext;
|
||||
JoinRestrictionContext *joinRestrictionContext =
|
||||
plannerRestrictionContext->joinRestrictionContext;
|
||||
|
||||
List *relationRestrictionAttributeEquivalenceList = NIL;
|
||||
List *joinRestrictionAttributeEquivalenceList = NIL;
|
||||
List *allAttributeEquivalenceList = NIL;
|
||||
|
@ -127,7 +134,6 @@ AllRelationsJoinedOnPartitionKey(RelationRestrictionContext *restrictionContext,
|
|||
uint32 referenceRelationCount = ReferenceRelationCount(restrictionContext);
|
||||
uint32 totalRelationCount = list_length(restrictionContext->relationRestrictionList);
|
||||
uint32 nonReferenceRelationCount = totalRelationCount - referenceRelationCount;
|
||||
|
||||
ListCell *commonEqClassCell = NULL;
|
||||
ListCell *relationRestrictionCell = NULL;
|
||||
Relids commonRteIdentities = NULL;
|
||||
|
@ -170,8 +176,9 @@ AllRelationsJoinedOnPartitionKey(RelationRestrictionContext *restrictionContext,
|
|||
/* add the rte indexes of relations to a bitmap */
|
||||
foreach(commonEqClassCell, commonEquivalenceClass->equivalentAttributes)
|
||||
{
|
||||
AttributeEquivalenceClassMember *classMember = lfirst(commonEqClassCell);
|
||||
int rteIdentity = classMember->rteIdendity;
|
||||
AttributeEquivalenceClassMember *classMember =
|
||||
(AttributeEquivalenceClassMember *) lfirst(commonEqClassCell);
|
||||
int rteIdentity = classMember->rteIdentity;
|
||||
|
||||
commonRteIdentities = bms_add_member(commonRteIdentities, rteIdentity);
|
||||
}
|
||||
|
@ -179,7 +186,8 @@ AllRelationsJoinedOnPartitionKey(RelationRestrictionContext *restrictionContext,
|
|||
/* check whether all relations exists in the main restriction list */
|
||||
foreach(relationRestrictionCell, restrictionContext->relationRestrictionList)
|
||||
{
|
||||
RelationRestriction *relationRestriction = lfirst(relationRestrictionCell);
|
||||
RelationRestriction *relationRestriction =
|
||||
(RelationRestriction *) lfirst(relationRestrictionCell);
|
||||
int rteIdentity = GetRTEIdentity(relationRestriction->rte);
|
||||
|
||||
if (PartitionKey(relationRestriction->relationId) &&
|
||||
|
@ -205,7 +213,8 @@ ReferenceRelationCount(RelationRestrictionContext *restrictionContext)
|
|||
|
||||
foreach(relationRestrictionCell, restrictionContext->relationRestrictionList)
|
||||
{
|
||||
RelationRestriction *relationRestriction = lfirst(relationRestrictionCell);
|
||||
RelationRestriction *relationRestriction =
|
||||
(RelationRestriction *) lfirst(relationRestrictionCell);
|
||||
|
||||
if (PartitionMethod(relationRestriction->relationId) == DISTRIBUTE_BY_NONE)
|
||||
{
|
||||
|
@ -243,21 +252,23 @@ GenerateAttributeEquivalencesForRelationRestrictions(RelationRestrictionContext
|
|||
|
||||
foreach(relationRestrictionCell, restrictionContext->relationRestrictionList)
|
||||
{
|
||||
RelationRestriction *relationRestriction = lfirst(relationRestrictionCell);
|
||||
RelationRestriction *relationRestriction =
|
||||
(RelationRestriction *) lfirst(relationRestrictionCell);
|
||||
List *equivalenceClasses = relationRestriction->plannerInfo->eq_classes;
|
||||
ListCell *equivilanceClassCell = NULL;
|
||||
ListCell *equivalenceClassCell = NULL;
|
||||
|
||||
foreach(equivilanceClassCell, equivalenceClasses)
|
||||
foreach(equivalenceClassCell, equivalenceClasses)
|
||||
{
|
||||
EquivalenceClass *plannerEqClass = lfirst(equivilanceClassCell);
|
||||
EquivalenceClass *plannerEqClass =
|
||||
(EquivalenceClass *) lfirst(equivalenceClassCell);
|
||||
|
||||
AttributeEquivalenceClass *attributeEquivalance =
|
||||
AttributeEquivalenceClassForEquivalenceClass(plannerEqClass,
|
||||
relationRestriction);
|
||||
|
||||
attributeEquivalenceList =
|
||||
AddAttributeClassToAttributeClassList(attributeEquivalance,
|
||||
attributeEquivalenceList);
|
||||
AddAttributeClassToAttributeClassList(attributeEquivalenceList,
|
||||
attributeEquivalance);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -288,7 +299,8 @@ AttributeEquivalenceClassForEquivalenceClass(EquivalenceClass *plannerEqClass,
|
|||
|
||||
foreach(equivilanceMemberCell, plannerEqClass->ec_members)
|
||||
{
|
||||
EquivalenceMember *equivalenceMember = lfirst(equivilanceMemberCell);
|
||||
EquivalenceMember *equivalenceMember =
|
||||
(EquivalenceMember *) lfirst(equivilanceMemberCell);
|
||||
Node *equivalenceNode = strip_implicit_coercions(
|
||||
(Node *) equivalenceMember->em_expr);
|
||||
Expr *strippedEquivalenceExpr = (Expr *) equivalenceNode;
|
||||
|
@ -304,17 +316,16 @@ AttributeEquivalenceClassForEquivalenceClass(EquivalenceClass *plannerEqClass,
|
|||
equivalenceParam);
|
||||
if (expressionVar)
|
||||
{
|
||||
AddToAttributeEquivalenceClass(
|
||||
relationRestriction->parentPlannerInfo,
|
||||
expressionVar,
|
||||
&attributeEquivalance);
|
||||
AddToAttributeEquivalenceClass(&attributeEquivalance,
|
||||
relationRestriction->parentPlannerInfo,
|
||||
expressionVar);
|
||||
}
|
||||
}
|
||||
else if (IsA(strippedEquivalenceExpr, Var))
|
||||
{
|
||||
expressionVar = (Var *) strippedEquivalenceExpr;
|
||||
AddToAttributeEquivalenceClass(plannerInfo, expressionVar,
|
||||
&attributeEquivalance);
|
||||
AddToAttributeEquivalenceClass(&attributeEquivalance, plannerInfo,
|
||||
expressionVar);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -368,7 +379,8 @@ GetVarFromAssignedParam(List *parentPlannerParamList, Param *plannerParam)
|
|||
|
||||
foreach(plannerParameterCell, parentPlannerParamList)
|
||||
{
|
||||
PlannerParamItem *plannerParamItem = lfirst(plannerParameterCell);
|
||||
PlannerParamItem *plannerParamItem =
|
||||
(PlannerParamItem *) lfirst(plannerParameterCell);
|
||||
|
||||
if (plannerParamItem->paramId != plannerParam->paramid)
|
||||
{
|
||||
|
@ -498,7 +510,8 @@ ListConcatUniqueAttributeClassMemberLists(AttributeEquivalenceClass **firstClass
|
|||
|
||||
foreach(equivalenceClassMemberCell, equivalenceMemberList)
|
||||
{
|
||||
AttributeEquivalenceClassMember *newEqMember = lfirst(equivalenceClassMemberCell);
|
||||
AttributeEquivalenceClassMember *newEqMember =
|
||||
(AttributeEquivalenceClassMember *) lfirst(equivalenceClassMemberCell);
|
||||
|
||||
if (AttributeClassContainsAttributeClassMember(newEqMember, *firstClass))
|
||||
{
|
||||
|
@ -532,7 +545,8 @@ GenerateAttributeEquivalencesForJoinRestrictions(JoinRestrictionContext *
|
|||
|
||||
foreach(joinRestrictionCell, joinRestrictionContext->joinRestrictionList)
|
||||
{
|
||||
JoinRestriction *joinRestriction = lfirst(joinRestrictionCell);
|
||||
JoinRestriction *joinRestriction =
|
||||
(JoinRestriction *) lfirst(joinRestrictionCell);
|
||||
ListCell *restrictionInfoList = NULL;
|
||||
|
||||
foreach(restrictionInfoList, joinRestriction->joinRestrictInfoList)
|
||||
|
@ -581,14 +595,15 @@ GenerateAttributeEquivalencesForJoinRestrictions(JoinRestrictionContext *
|
|||
attributeEquivalance = palloc0(sizeof(AttributeEquivalenceClass));
|
||||
attributeEquivalance->equivalenceId = attributeEquivalenceId++;
|
||||
|
||||
AddToAttributeEquivalenceClass(joinRestriction->plannerInfo, leftVar,
|
||||
&attributeEquivalance);
|
||||
AddToAttributeEquivalenceClass(joinRestriction->plannerInfo, rightVar,
|
||||
&attributeEquivalance);
|
||||
AddToAttributeEquivalenceClass(&attributeEquivalance,
|
||||
joinRestriction->plannerInfo, leftVar);
|
||||
|
||||
AddToAttributeEquivalenceClass(&attributeEquivalance,
|
||||
joinRestriction->plannerInfo, rightVar);
|
||||
|
||||
attributeEquivalenceList =
|
||||
AddAttributeClassToAttributeClassList(attributeEquivalance,
|
||||
attributeEquivalenceList);
|
||||
AddAttributeClassToAttributeClassList(attributeEquivalenceList,
|
||||
attributeEquivalance);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -624,8 +639,8 @@ GenerateAttributeEquivalencesForJoinRestrictions(JoinRestrictionContext *
|
|||
* This implies that there wouldn't be any columns for reference tables.
|
||||
*/
|
||||
static void
|
||||
AddToAttributeEquivalenceClass(PlannerInfo *root, Var *varToBeAdded,
|
||||
AttributeEquivalenceClass **attributeEquivalanceClass)
|
||||
AddToAttributeEquivalenceClass(AttributeEquivalenceClass **attributeEquivalanceClass,
|
||||
PlannerInfo *root, Var *varToBeAdded)
|
||||
{
|
||||
RangeTblEntry *rangeTableEntry = root->simple_rte_array[varToBeAdded->varno];
|
||||
|
||||
|
@ -650,7 +665,7 @@ AddToAttributeEquivalenceClass(PlannerInfo *root, Var *varToBeAdded,
|
|||
|
||||
attributeEqMember->varattno = varToBeAdded->varattno;
|
||||
attributeEqMember->varno = varToBeAdded->varno;
|
||||
attributeEqMember->rteIdendity = GetRTEIdentity(rangeTableEntry);
|
||||
attributeEqMember->rteIdentity = GetRTEIdentity(rangeTableEntry);
|
||||
attributeEqMember->relationId = rangeTableEntry->relid;
|
||||
|
||||
(*attributeEquivalanceClass)->equivalentAttributes =
|
||||
|
@ -669,6 +684,12 @@ AddToAttributeEquivalenceClass(PlannerInfo *root, Var *varToBeAdded,
|
|||
return;
|
||||
}
|
||||
|
||||
/* we also don't want to process ctid, tableoid etc */
|
||||
if (varToBeAdded->varattno < InvalidAttrNumber)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
baseRelOptInfo = find_base_rel(root, varToBeAdded->varno);
|
||||
|
||||
/* If the subquery hasn't been planned yet, we have to punt */
|
||||
|
@ -710,17 +731,17 @@ AddToAttributeEquivalenceClass(PlannerInfo *root, Var *varToBeAdded,
|
|||
RangeTblRef *rightRangeTableReference = (RangeTblRef *) unionStatement->rarg;
|
||||
|
||||
varToBeAdded->varno = leftRangeTableReference->rtindex;
|
||||
AddToAttributeEquivalenceClass(baseRelOptInfo->subroot, varToBeAdded,
|
||||
attributeEquivalanceClass);
|
||||
AddToAttributeEquivalenceClass(attributeEquivalanceClass,
|
||||
baseRelOptInfo->subroot, varToBeAdded);
|
||||
|
||||
varToBeAdded->varno = rightRangeTableReference->rtindex;
|
||||
AddToAttributeEquivalenceClass(baseRelOptInfo->subroot, varToBeAdded,
|
||||
attributeEquivalanceClass);
|
||||
AddToAttributeEquivalenceClass(attributeEquivalanceClass,
|
||||
baseRelOptInfo->subroot, varToBeAdded);
|
||||
}
|
||||
else if (varToBeAdded && IsA(varToBeAdded, Var) && varToBeAdded->varlevelsup == 0)
|
||||
{
|
||||
AddToAttributeEquivalenceClass(baseRelOptInfo->subroot, varToBeAdded,
|
||||
attributeEquivalanceClass);
|
||||
AddToAttributeEquivalenceClass(attributeEquivalanceClass,
|
||||
baseRelOptInfo->subroot, varToBeAdded);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -739,8 +760,9 @@ AttributeClassContainsAttributeClassMember(AttributeEquivalenceClassMember *inpu
|
|||
ListCell *classCell = NULL;
|
||||
foreach(classCell, attributeEquivalenceClass->equivalentAttributes)
|
||||
{
|
||||
AttributeEquivalenceClassMember *memberOfClass = lfirst(classCell);
|
||||
if (memberOfClass->rteIdendity == inputMember->rteIdendity &&
|
||||
AttributeEquivalenceClassMember *memberOfClass =
|
||||
(AttributeEquivalenceClassMember *) lfirst(classCell);
|
||||
if (memberOfClass->rteIdentity == inputMember->rteIdentity &&
|
||||
memberOfClass->varattno == inputMember->varattno)
|
||||
{
|
||||
return true;
|
||||
|
@ -760,8 +782,8 @@ AttributeClassContainsAttributeClassMember(AttributeEquivalenceClassMember *inpu
|
|||
* not contribute to our purposes, we skip such classed adding to the list.
|
||||
*/
|
||||
static List *
|
||||
AddAttributeClassToAttributeClassList(AttributeEquivalenceClass *attributeEquivalance,
|
||||
List *attributeEquivalenceList)
|
||||
AddAttributeClassToAttributeClassList(List *attributeEquivalenceList,
|
||||
AttributeEquivalenceClass *attributeEquivalance)
|
||||
{
|
||||
List *equivalentAttributes = NULL;
|
||||
|
||||
|
|
|
@ -32,8 +32,7 @@
|
|||
#include "utils/memutils.h"
|
||||
|
||||
|
||||
static List *relationRestrictionContextList = NIL;
|
||||
static List *joinRestrictionContextList = NIL;
|
||||
static List *plannerRestrictionContextList = NIL;
|
||||
|
||||
/* create custom scan methods for separate executors */
|
||||
static CustomScanMethods RealTimeCustomScanMethods = {
|
||||
|
@ -60,8 +59,8 @@ static CustomScanMethods DelayedErrorCustomScanMethods = {
|
|||
/* local function forward declarations */
|
||||
static PlannedStmt * CreateDistributedPlan(PlannedStmt *localPlan, Query *originalQuery,
|
||||
Query *query, ParamListInfo boundParams,
|
||||
RelationRestrictionContext *restrictionContext,
|
||||
JoinRestrictionContext *joinRestrictionContext);
|
||||
PlannerRestrictionContext *
|
||||
plannerRestrictionContext);
|
||||
static void AssignRTEIdentities(Query *queryTree);
|
||||
static void AssignRTEIdentity(RangeTblEntry *rangeTableEntry, int rteIdentifier);
|
||||
static Node * SerializeMultiPlan(struct MultiPlan *multiPlan);
|
||||
|
@ -72,10 +71,10 @@ static PlannedStmt * FinalizeNonRouterPlan(PlannedStmt *localPlan, MultiPlan *mu
|
|||
static PlannedStmt * FinalizeRouterPlan(PlannedStmt *localPlan, CustomScan *customScan);
|
||||
static void CheckNodeIsDumpable(Node *node);
|
||||
static List * CopyPlanParamList(List *originalPlanParamList);
|
||||
static void CreateAndPushPlannerContexts(void);
|
||||
static RelationRestrictionContext * CurrentRestrictionContext(void);
|
||||
static PlannerRestrictionContext * CreateAndPushPlannerRestrictionContext(void);
|
||||
static RelationRestrictionContext * CurrentRelationRestrictionContext(void);
|
||||
static JoinRestrictionContext * CurrentJoinRestrictionContext(void);
|
||||
static void PopRestrictionContexts(void);
|
||||
static void PopPlannerRestrictionContext(void);
|
||||
static bool HasUnresolvedExternParamsWalker(Node *expression, ParamListInfo boundParams);
|
||||
|
||||
|
||||
|
@ -86,8 +85,7 @@ multi_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
|
|||
PlannedStmt *result = NULL;
|
||||
bool needsDistributedPlanning = NeedsDistributedPlanning(parse);
|
||||
Query *originalQuery = NULL;
|
||||
RelationRestrictionContext *relationRestrictionContext = NULL;
|
||||
JoinRestrictionContext *joinRestrictionContext = NULL;
|
||||
PlannerRestrictionContext *plannerRestrictionContext = NULL;
|
||||
|
||||
/*
|
||||
* standard_planner scribbles on it's input, but for deparsing we need the
|
||||
|
@ -101,10 +99,7 @@ multi_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
|
|||
}
|
||||
|
||||
/* create a restriction context and put it at the end if context list */
|
||||
CreateAndPushPlannerContexts();
|
||||
|
||||
relationRestrictionContext = CurrentRestrictionContext();
|
||||
joinRestrictionContext = CurrentJoinRestrictionContext();
|
||||
plannerRestrictionContext = CreateAndPushPlannerRestrictionContext();
|
||||
|
||||
PG_TRY();
|
||||
{
|
||||
|
@ -118,19 +113,18 @@ multi_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
|
|||
if (needsDistributedPlanning)
|
||||
{
|
||||
result = CreateDistributedPlan(result, originalQuery, parse,
|
||||
boundParams, relationRestrictionContext,
|
||||
joinRestrictionContext);
|
||||
boundParams, plannerRestrictionContext);
|
||||
}
|
||||
}
|
||||
PG_CATCH();
|
||||
{
|
||||
PopRestrictionContexts();
|
||||
PopPlannerRestrictionContext();
|
||||
PG_RE_THROW();
|
||||
}
|
||||
PG_END_TRY();
|
||||
|
||||
/* remove the context from the context list */
|
||||
PopRestrictionContexts();
|
||||
PopPlannerRestrictionContext();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -187,6 +181,18 @@ AssignRTEIdentity(RangeTblEntry *rangeTableEntry, int rteIdentifier)
|
|||
}
|
||||
|
||||
|
||||
/* GetRTEIdentity returns the identity assigned with AssignRTEIdentity. */
|
||||
int
|
||||
GetRTEIdentity(RangeTblEntry *rte)
|
||||
{
|
||||
Assert(rte->rtekind == RTE_RELATION);
|
||||
Assert(IsA(rte->values_lists, IntList));
|
||||
Assert(list_length(rte->values_lists) == 1);
|
||||
|
||||
return linitial_int(rte->values_lists);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* IsModifyCommand returns true if the query performs modifications, false
|
||||
* otherwise.
|
||||
|
@ -232,8 +238,7 @@ IsModifyMultiPlan(MultiPlan *multiPlan)
|
|||
static PlannedStmt *
|
||||
CreateDistributedPlan(PlannedStmt *localPlan, Query *originalQuery, Query *query,
|
||||
ParamListInfo boundParams,
|
||||
RelationRestrictionContext *restrictionContext,
|
||||
JoinRestrictionContext *joinRestrictionContext)
|
||||
PlannerRestrictionContext *plannerRestrictionContext)
|
||||
{
|
||||
MultiPlan *distributedPlan = NULL;
|
||||
PlannedStmt *resultPlan = NULL;
|
||||
|
@ -247,8 +252,8 @@ CreateDistributedPlan(PlannedStmt *localPlan, Query *originalQuery, Query *query
|
|||
if (IsModifyCommand(query))
|
||||
{
|
||||
/* modifications are always routed through the same planner/executor */
|
||||
distributedPlan = CreateModifyPlan(originalQuery, query, restrictionContext,
|
||||
joinRestrictionContext);
|
||||
distributedPlan =
|
||||
CreateModifyPlan(originalQuery, query, plannerRestrictionContext);
|
||||
|
||||
Assert(distributedPlan);
|
||||
}
|
||||
|
@ -262,7 +267,11 @@ CreateDistributedPlan(PlannedStmt *localPlan, Query *originalQuery, Query *query
|
|||
*/
|
||||
if (EnableRouterExecution)
|
||||
{
|
||||
distributedPlan = CreateRouterPlan(originalQuery, query, restrictionContext);
|
||||
RelationRestrictionContext *relationRestrictionContext =
|
||||
plannerRestrictionContext->relationRestrictionContext;
|
||||
|
||||
distributedPlan = CreateRouterPlan(originalQuery, query,
|
||||
relationRestrictionContext);
|
||||
|
||||
/* for debugging it's useful to display why query was not router plannable */
|
||||
if (distributedPlan && distributedPlan->planningError)
|
||||
|
@ -639,7 +648,6 @@ multi_join_restriction_hook(PlannerInfo *root,
|
|||
joinRestriction->joinRestrictInfoList = restrictInfoList;
|
||||
joinRestriction->plannerInfo = root;
|
||||
|
||||
|
||||
joinContext->joinRestrictionList =
|
||||
lappend(joinContext->joinRestrictionList, joinRestriction);
|
||||
}
|
||||
|
@ -668,7 +676,7 @@ multi_relation_restriction_hook(PlannerInfo *root, RelOptInfo *relOptInfo, Index
|
|||
distributedTable = IsDistributedTable(rte->relid);
|
||||
localTable = !distributedTable;
|
||||
|
||||
restrictionContext = CurrentRestrictionContext();
|
||||
restrictionContext = CurrentRelationRestrictionContext();
|
||||
Assert(restrictionContext != NULL);
|
||||
|
||||
relationRestriction = palloc0(sizeof(RelationRestriction));
|
||||
|
@ -708,18 +716,6 @@ multi_relation_restriction_hook(PlannerInfo *root, RelOptInfo *relOptInfo, Index
|
|||
}
|
||||
|
||||
|
||||
/* GetRTEIdentity returns the identity assigned with AssignRTEIdentity. */
|
||||
int
|
||||
GetRTEIdentity(RangeTblEntry *rte)
|
||||
{
|
||||
Assert(rte->rtekind == RTE_RELATION);
|
||||
Assert(IsA(rte->values_lists, IntList));
|
||||
Assert(list_length(rte->values_lists) == 1);
|
||||
|
||||
return linitial_int(rte->values_lists);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* CopyPlanParamList deep copies the input PlannerParamItem list and returns the newly
|
||||
* allocated list.
|
||||
|
@ -748,43 +744,50 @@ CopyPlanParamList(List *originalPlanParamList)
|
|||
|
||||
|
||||
/*
|
||||
* CreateAndPushPlannerContextes creates a new restriction context and a new join context,
|
||||
* inserts it to the beginning of the respective context lists.
|
||||
* CreateAndPushPlannerRestrictionContext creates a new relation restriction context
|
||||
* and a new join context, inserts it to the beginning of the
|
||||
* plannerRestrictionContextList.
|
||||
*/
|
||||
static void
|
||||
CreateAndPushPlannerContexts(void)
|
||||
static PlannerRestrictionContext *
|
||||
CreateAndPushPlannerRestrictionContext(void)
|
||||
{
|
||||
RelationRestrictionContext *restrictionContext =
|
||||
PlannerRestrictionContext *plannerRestrictionContext =
|
||||
palloc0(sizeof(PlannerRestrictionContext));
|
||||
|
||||
plannerRestrictionContext->relationRestrictionContext =
|
||||
palloc0(sizeof(RelationRestrictionContext));
|
||||
|
||||
JoinRestrictionContext *joinContext =
|
||||
plannerRestrictionContext->joinRestrictionContext =
|
||||
palloc0(sizeof(JoinRestrictionContext));
|
||||
|
||||
/* we'll apply logical AND as we add tables */
|
||||
restrictionContext->allReferenceTables = true;
|
||||
plannerRestrictionContext->relationRestrictionContext->allReferenceTables = true;
|
||||
|
||||
relationRestrictionContextList = lcons(restrictionContext,
|
||||
relationRestrictionContextList);
|
||||
joinRestrictionContextList = lcons(joinContext,
|
||||
joinRestrictionContextList);
|
||||
plannerRestrictionContextList = lcons(plannerRestrictionContext,
|
||||
plannerRestrictionContextList);
|
||||
|
||||
return plannerRestrictionContext;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* CurrentRestrictionContext returns the the last restriction context from the
|
||||
* list.
|
||||
* relationRestrictionContext list.
|
||||
*/
|
||||
static RelationRestrictionContext *
|
||||
CurrentRestrictionContext(void)
|
||||
CurrentRelationRestrictionContext(void)
|
||||
{
|
||||
RelationRestrictionContext *restrictionContext = NULL;
|
||||
PlannerRestrictionContext *plannerRestrictionContext = NULL;
|
||||
RelationRestrictionContext *relationRestrictionContext = NULL;
|
||||
|
||||
Assert(relationRestrictionContextList != NIL);
|
||||
Assert(plannerRestrictionContextList != NIL);
|
||||
|
||||
restrictionContext =
|
||||
(RelationRestrictionContext *) linitial(relationRestrictionContextList);
|
||||
plannerRestrictionContext =
|
||||
(PlannerRestrictionContext *) linitial(plannerRestrictionContextList);
|
||||
|
||||
return restrictionContext;
|
||||
relationRestrictionContext = plannerRestrictionContext->relationRestrictionContext;
|
||||
|
||||
return relationRestrictionContext;
|
||||
}
|
||||
|
||||
|
||||
|
@ -795,25 +798,28 @@ CurrentRestrictionContext(void)
|
|||
static JoinRestrictionContext *
|
||||
CurrentJoinRestrictionContext(void)
|
||||
{
|
||||
JoinRestrictionContext *joinContext = NULL;
|
||||
PlannerRestrictionContext *plannerRestrictionContext = NULL;
|
||||
JoinRestrictionContext *joinRestrictionContext = NULL;
|
||||
|
||||
Assert(joinRestrictionContextList != NIL);
|
||||
Assert(plannerRestrictionContextList != NIL);
|
||||
|
||||
joinContext = (JoinRestrictionContext *) linitial(joinRestrictionContextList);
|
||||
plannerRestrictionContext =
|
||||
(PlannerRestrictionContext *) linitial(plannerRestrictionContextList);
|
||||
|
||||
return joinContext;
|
||||
joinRestrictionContext = plannerRestrictionContext->joinRestrictionContext;
|
||||
|
||||
return joinRestrictionContext;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* PopRestrictionContexts removes the most recently added restriction contexts from
|
||||
* the restriction and join context lists. The function assumes the lists are not empty.
|
||||
* PopPlannerRestrictionContext removes the most recently added restriction contexts from
|
||||
* the planner restriction context list. The function assumes the list is not empty.
|
||||
*/
|
||||
static void
|
||||
PopRestrictionContexts(void)
|
||||
PopPlannerRestrictionContext(void)
|
||||
{
|
||||
relationRestrictionContextList = list_delete_first(relationRestrictionContextList);
|
||||
joinRestrictionContextList = list_delete_first(joinRestrictionContextList);
|
||||
plannerRestrictionContextList = list_delete_first(plannerRestrictionContextList);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -85,11 +85,8 @@ static MultiPlan * CreateSingleTaskRouterPlan(Query *originalQuery,
|
|||
RelationRestrictionContext *
|
||||
restrictionContext);
|
||||
static MultiPlan * CreateInsertSelectRouterPlan(Query *originalQuery,
|
||||
RelationRestrictionContext *
|
||||
restrictionContext,
|
||||
JoinRestrictionContext *
|
||||
joinRestrictionContext);
|
||||
|
||||
PlannerRestrictionContext *
|
||||
plannerRestrictionContext);
|
||||
static Task * RouterModifyTaskForShardInterval(Query *originalQuery,
|
||||
ShardInterval *shardInterval,
|
||||
RelationRestrictionContext *
|
||||
|
@ -171,18 +168,19 @@ CreateRouterPlan(Query *originalQuery, Query *query,
|
|||
*/
|
||||
MultiPlan *
|
||||
CreateModifyPlan(Query *originalQuery, Query *query,
|
||||
RelationRestrictionContext *restrictionContext,
|
||||
JoinRestrictionContext *joinRestrictionContext)
|
||||
PlannerRestrictionContext *plannerRestrictionContext)
|
||||
{
|
||||
if (InsertSelectQuery(originalQuery))
|
||||
{
|
||||
return CreateInsertSelectRouterPlan(originalQuery, restrictionContext,
|
||||
joinRestrictionContext);
|
||||
return CreateInsertSelectRouterPlan(originalQuery, plannerRestrictionContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
RelationRestrictionContext *relationRestrictionContext =
|
||||
plannerRestrictionContext->relationRestrictionContext;
|
||||
|
||||
return CreateSingleTaskRouterPlan(originalQuery, query,
|
||||
restrictionContext);
|
||||
relationRestrictionContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -266,8 +264,7 @@ CreateSingleTaskRouterPlan(Query *originalQuery, Query *query,
|
|||
*/
|
||||
static MultiPlan *
|
||||
CreateInsertSelectRouterPlan(Query *originalQuery,
|
||||
RelationRestrictionContext *restrictionContext,
|
||||
JoinRestrictionContext *joinRestrictionContext)
|
||||
PlannerRestrictionContext *plannerRestrictionContext)
|
||||
{
|
||||
int shardOffset = 0;
|
||||
List *sqlTaskList = NIL;
|
||||
|
@ -280,7 +277,9 @@ CreateInsertSelectRouterPlan(Query *originalQuery,
|
|||
Oid targetRelationId = insertRte->relid;
|
||||
DistTableCacheEntry *targetCacheEntry = DistributedTableCacheEntry(targetRelationId);
|
||||
int shardCount = targetCacheEntry->shardIntervalArrayLength;
|
||||
bool allReferenceTables = restrictionContext->allReferenceTables;
|
||||
RelationRestrictionContext *relationRestrictionContext =
|
||||
plannerRestrictionContext->relationRestrictionContext;
|
||||
bool allReferenceTables = relationRestrictionContext->allReferenceTables;
|
||||
bool allRelationsJoinedOnPartitionKey = false;
|
||||
|
||||
multiPlan->operation = originalQuery->commandType;
|
||||
|
@ -298,7 +297,7 @@ CreateInsertSelectRouterPlan(Query *originalQuery,
|
|||
}
|
||||
|
||||
allRelationsJoinedOnPartitionKey =
|
||||
AllRelationsJoinedOnPartitionKey(restrictionContext, joinRestrictionContext);
|
||||
AllRelationsJoinedOnPartitionKey(plannerRestrictionContext);
|
||||
|
||||
/*
|
||||
* Plan select query for each shard in the target table. Do so by replacing the
|
||||
|
@ -316,7 +315,8 @@ CreateInsertSelectRouterPlan(Query *originalQuery,
|
|||
Task *modifyTask = NULL;
|
||||
|
||||
modifyTask = RouterModifyTaskForShardInterval(originalQuery, targetShardInterval,
|
||||
restrictionContext, taskIdIndex,
|
||||
relationRestrictionContext,
|
||||
taskIdIndex,
|
||||
allRelationsJoinedOnPartitionKey);
|
||||
|
||||
/* add the task if it could be created */
|
||||
|
|
|
@ -15,10 +15,8 @@
|
|||
#include "distributed/multi_planner.h"
|
||||
|
||||
|
||||
extern bool AllRelationsJoinedOnPartitionKey(RelationRestrictionContext *
|
||||
restrictionContext,
|
||||
JoinRestrictionContext *
|
||||
joinRestrictionContext);
|
||||
extern bool AllRelationsJoinedOnPartitionKey(PlannerRestrictionContext *
|
||||
plannerRestrictionContext);
|
||||
|
||||
|
||||
#endif /* MULTI_COLOCATED_SUBQUERY_PLANNER_H */
|
||||
|
|
|
@ -54,6 +54,12 @@ typedef struct JoinRestriction
|
|||
PlannerInfo *plannerInfo;
|
||||
} JoinRestriction;
|
||||
|
||||
typedef struct PlannerRestrictionContext
|
||||
{
|
||||
RelationRestrictionContext *relationRestrictionContext;
|
||||
JoinRestrictionContext *joinRestrictionContext;
|
||||
} PlannerRestrictionContext;
|
||||
|
||||
typedef struct RelationShard
|
||||
{
|
||||
CitusNode type;
|
||||
|
|
|
@ -29,8 +29,8 @@ extern bool EnableRouterExecution;
|
|||
extern MultiPlan * CreateRouterPlan(Query *originalQuery, Query *query,
|
||||
RelationRestrictionContext *restrictionContext);
|
||||
extern MultiPlan * CreateModifyPlan(Query *originalQuery, Query *query,
|
||||
RelationRestrictionContext *restrictionContext,
|
||||
JoinRestrictionContext *joinRestrictionContext);
|
||||
PlannerRestrictionContext *
|
||||
plannerRestrictionContext);
|
||||
|
||||
extern DeferredErrorMessage * ModifyQuerySupported(Query *queryTree);
|
||||
extern Query * ReorderInsertSelectTargetLists(Query *originalQuery,
|
||||
|
|
Loading…
Reference in New Issue