mirror of https://github.com/citusdata/citus.git
Decide what group to convert, then convert them all in one go
parent
c4d3927956
commit
d5b0f02a64
|
@ -135,7 +135,6 @@ int LocalTableJoinPolicy = LOCAL_JOIN_POLICY_AUTO;
|
|||
typedef struct RangeTableEntryDetails
|
||||
{
|
||||
RangeTblEntry *rangeTableEntry;
|
||||
int rteIdentity;
|
||||
List *requiredAttributeNumbers;
|
||||
bool hasConstantFilterOnUniqueColumn;
|
||||
} RangeTableEntryDetails;
|
||||
|
@ -151,6 +150,12 @@ typedef struct IndexColumns
|
|||
List *indexColumnNos;
|
||||
}IndexColumns;
|
||||
|
||||
typedef enum ConversionChoice
|
||||
{
|
||||
CONVERT_LOCAL_TABLES = 1,
|
||||
CONVERT_DISTRIBUTED_TABLES = 2
|
||||
}ConversionChoice;
|
||||
|
||||
static bool HasConstantFilterOnUniqueColumn(RangeTblEntry *rangeTableEntry,
|
||||
RelationRestriction *relationRestriction);
|
||||
static List * RequiredAttrNumbersForRelation(RangeTblEntry *relationRte,
|
||||
|
@ -161,14 +166,14 @@ static ConversionCandidates * CreateConversionCandidates(PlannerRestrictionConte
|
|||
List *rangeTableList,
|
||||
int resultRTEIdentity);
|
||||
static void AppendUniqueIndexColumnsToList(Form_pg_index indexForm, List **uniqueIndexes);
|
||||
static RangeTableEntryDetails * GetNextRTEToConvertToSubquery(ConversionCandidates *
|
||||
conversionCandidates,
|
||||
PlannerRestrictionContext *
|
||||
plannerRestrictionContext);
|
||||
static void RemoveFromConversionCandidates(ConversionCandidates *conversionCandidates,
|
||||
int rteIdentity);
|
||||
static ConversionChoice GetConversionChoice(ConversionCandidates *
|
||||
conversionCandidates,
|
||||
PlannerRestrictionContext *
|
||||
plannerRestrictionContext);
|
||||
static bool AllRangeTableEntriesHaveUniqueIndex(List *rangeTableEntryDetailsList);
|
||||
static bool FirstIsSuperSetOfSecond(List *firstIntList, List *secondIntList);
|
||||
static void ConvertRTEsToSubquery(List *rangeTableEntryDetailsList,
|
||||
RecursivePlanningContext *context);
|
||||
|
||||
/*
|
||||
* RecursivelyPlanLocalTableJoins gets a query and the planner
|
||||
|
@ -192,35 +197,27 @@ RecursivelyPlanLocalTableJoins(Query *query,
|
|||
CreateConversionCandidates(plannerRestrictionContext,
|
||||
rangeTableList, resultRTEIdentity);
|
||||
|
||||
while (ShouldConvertLocalTableJoinsToSubqueries(query, rangeTableList,
|
||||
plannerRestrictionContext))
|
||||
{
|
||||
RangeTableEntryDetails *rangeTableEntryDetails =
|
||||
GetNextRTEToConvertToSubquery(conversionCandidates,
|
||||
plannerRestrictionContext);
|
||||
if (rangeTableEntryDetails == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
ConversionChoice conversionChoise =
|
||||
GetConversionChoice(conversionCandidates, plannerRestrictionContext);
|
||||
|
||||
RangeTblEntry *rangeTableEntry = rangeTableEntryDetails->rangeTableEntry;
|
||||
List *requiredAttributeNumbers = rangeTableEntryDetails->requiredAttributeNumbers;
|
||||
ReplaceRTERelationWithRteSubquery(rangeTableEntry,
|
||||
requiredAttributeNumbers, context);
|
||||
int rteIdentity = rangeTableEntryDetails->rteIdentity;
|
||||
RemoveFromConversionCandidates(conversionCandidates, rteIdentity);
|
||||
if (conversionChoise == CONVERT_LOCAL_TABLES)
|
||||
{
|
||||
ConvertRTEsToSubquery(conversionCandidates->localTableList, context);
|
||||
}
|
||||
else
|
||||
{
|
||||
ConvertRTEsToSubquery(conversionCandidates->distributedTableList, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* GetNextRTEToConvertToSubquery returns the range table entry
|
||||
* which should be converted to a subquery. It considers the local join policy
|
||||
* for conversion priorities.
|
||||
* GetConversionChoice returns the conversion choice considering the local table
|
||||
* join policy.
|
||||
*/
|
||||
static RangeTableEntryDetails *
|
||||
GetNextRTEToConvertToSubquery(ConversionCandidates *conversionCandidates,
|
||||
PlannerRestrictionContext *plannerRestrictionContext)
|
||||
static ConversionChoice
|
||||
GetConversionChoice(ConversionCandidates *conversionCandidates,
|
||||
PlannerRestrictionContext *plannerRestrictionContext)
|
||||
{
|
||||
RangeTableEntryDetails *localRTECandidate = NULL;
|
||||
RangeTableEntryDetails *distributedRTECandidate = NULL;
|
||||
|
@ -236,11 +233,12 @@ GetNextRTEToConvertToSubquery(ConversionCandidates *conversionCandidates,
|
|||
|
||||
if (LocalTableJoinPolicy == LOCAL_JOIN_POLICY_PREFER_LOCAL)
|
||||
{
|
||||
return localRTECandidate ? localRTECandidate : distributedRTECandidate;
|
||||
return localRTECandidate ? CONVERT_LOCAL_TABLES : CONVERT_DISTRIBUTED_TABLES;
|
||||
}
|
||||
else if (LocalTableJoinPolicy == LOCAL_JOIN_POLICY_PREFER_DISTRIBUTED)
|
||||
{
|
||||
return distributedRTECandidate ? distributedRTECandidate : localRTECandidate;
|
||||
return distributedRTECandidate ? CONVERT_DISTRIBUTED_TABLES :
|
||||
CONVERT_LOCAL_TABLES;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -254,16 +252,35 @@ GetNextRTEToConvertToSubquery(ConversionCandidates *conversionCandidates,
|
|||
|
||||
if (allRangeTableEntriesHaveUniqueIndex)
|
||||
{
|
||||
return distributedRTECandidate ? distributedRTECandidate : localRTECandidate;
|
||||
return distributedRTECandidate ? CONVERT_DISTRIBUTED_TABLES :
|
||||
CONVERT_LOCAL_TABLES;
|
||||
}
|
||||
else
|
||||
{
|
||||
return localRTECandidate ? localRTECandidate : distributedRTECandidate;
|
||||
return localRTECandidate ? CONVERT_LOCAL_TABLES : CONVERT_DISTRIBUTED_TABLES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ConvertRTEsToSubquery converts all the given range table entries
|
||||
* to a subquery.
|
||||
*/
|
||||
static void
|
||||
ConvertRTEsToSubquery(List *rangeTableEntryDetailsList, RecursivePlanningContext *context)
|
||||
{
|
||||
RangeTableEntryDetails *rangeTableEntryDetails = NULL;
|
||||
foreach_ptr(rangeTableEntryDetails, rangeTableEntryDetailsList)
|
||||
{
|
||||
RangeTblEntry *rangeTableEntry = rangeTableEntryDetails->rangeTableEntry;
|
||||
List *requiredAttributeNumbers = rangeTableEntryDetails->requiredAttributeNumbers;
|
||||
ReplaceRTERelationWithRteSubquery(rangeTableEntry,
|
||||
requiredAttributeNumbers, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* AllRangeTableEntriesHaveUniqueIndex returns true if all of the RTE's in the given
|
||||
* list have a unique index.
|
||||
|
@ -283,41 +300,6 @@ AllRangeTableEntriesHaveUniqueIndex(List *rangeTableEntryDetailsList)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* RemoveFromConversionCandidates removes an element from
|
||||
* the relevant list based on the relation id.
|
||||
*/
|
||||
static void
|
||||
RemoveFromConversionCandidates(ConversionCandidates *conversionCandidates, int
|
||||
rteIdentity)
|
||||
{
|
||||
RangeTableEntryDetails *rangeTableEntryDetails = NULL;
|
||||
foreach_ptr(rangeTableEntryDetails, conversionCandidates->localTableList)
|
||||
{
|
||||
if (rangeTableEntryDetails->rteIdentity == rteIdentity)
|
||||
{
|
||||
conversionCandidates->localTableList =
|
||||
list_delete_ptr(conversionCandidates->localTableList,
|
||||
rangeTableEntryDetails);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
foreach_ptr(rangeTableEntryDetails, conversionCandidates->distributedTableList)
|
||||
{
|
||||
if (rangeTableEntryDetails->rteIdentity == rteIdentity)
|
||||
{
|
||||
conversionCandidates->distributedTableList =
|
||||
list_delete_ptr(conversionCandidates->distributedTableList,
|
||||
rangeTableEntryDetails);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ereport(ERROR, (errmsg("invalid rte index is given :%d", rteIdentity)));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ShouldConvertLocalTableJoinsToSubqueries returns true if we should
|
||||
* convert local-dist table joins to subqueries.
|
||||
|
@ -506,7 +488,6 @@ CreateConversionCandidates(PlannerRestrictionContext *plannerRestrictionContext,
|
|||
palloc0(sizeof(RangeTableEntryDetails));
|
||||
|
||||
rangeTableEntryDetails->rangeTableEntry = rangeTableEntry;
|
||||
rangeTableEntryDetails->rteIdentity = rteIdentity;
|
||||
rangeTableEntryDetails->requiredAttributeNumbers =
|
||||
RequiredAttrNumbersForRelation(rangeTableEntry, plannerRestrictionContext);
|
||||
rangeTableEntryDetails->hasConstantFilterOnUniqueColumn =
|
||||
|
|
|
@ -1793,6 +1793,7 @@ TransformFunctionRTE(RangeTblEntry *rangeTblEntry)
|
|||
subquery->targetList = lappend(subquery->targetList, targetEntry);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If tupleDesc is NULL we have 2 different cases:
|
||||
*
|
||||
|
@ -1842,6 +1843,7 @@ TransformFunctionRTE(RangeTblEntry *rangeTblEntry)
|
|||
columnType = list_nth_oid(rangeTblFunction->funccoltypes,
|
||||
targetColumnIndex);
|
||||
}
|
||||
|
||||
/* use the types in the function definition otherwise */
|
||||
else
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue