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
|
typedef struct RangeTableEntryDetails
|
||||||
{
|
{
|
||||||
RangeTblEntry *rangeTableEntry;
|
RangeTblEntry *rangeTableEntry;
|
||||||
int rteIdentity;
|
|
||||||
List *requiredAttributeNumbers;
|
List *requiredAttributeNumbers;
|
||||||
bool hasConstantFilterOnUniqueColumn;
|
bool hasConstantFilterOnUniqueColumn;
|
||||||
} RangeTableEntryDetails;
|
} RangeTableEntryDetails;
|
||||||
|
@ -151,6 +150,12 @@ typedef struct IndexColumns
|
||||||
List *indexColumnNos;
|
List *indexColumnNos;
|
||||||
}IndexColumns;
|
}IndexColumns;
|
||||||
|
|
||||||
|
typedef enum ConversionChoice
|
||||||
|
{
|
||||||
|
CONVERT_LOCAL_TABLES = 1,
|
||||||
|
CONVERT_DISTRIBUTED_TABLES = 2
|
||||||
|
}ConversionChoice;
|
||||||
|
|
||||||
static bool HasConstantFilterOnUniqueColumn(RangeTblEntry *rangeTableEntry,
|
static bool HasConstantFilterOnUniqueColumn(RangeTblEntry *rangeTableEntry,
|
||||||
RelationRestriction *relationRestriction);
|
RelationRestriction *relationRestriction);
|
||||||
static List * RequiredAttrNumbersForRelation(RangeTblEntry *relationRte,
|
static List * RequiredAttrNumbersForRelation(RangeTblEntry *relationRte,
|
||||||
|
@ -161,14 +166,14 @@ static ConversionCandidates * CreateConversionCandidates(PlannerRestrictionConte
|
||||||
List *rangeTableList,
|
List *rangeTableList,
|
||||||
int resultRTEIdentity);
|
int resultRTEIdentity);
|
||||||
static void AppendUniqueIndexColumnsToList(Form_pg_index indexForm, List **uniqueIndexes);
|
static void AppendUniqueIndexColumnsToList(Form_pg_index indexForm, List **uniqueIndexes);
|
||||||
static RangeTableEntryDetails * GetNextRTEToConvertToSubquery(ConversionCandidates *
|
static ConversionChoice GetConversionChoice(ConversionCandidates *
|
||||||
conversionCandidates,
|
conversionCandidates,
|
||||||
PlannerRestrictionContext *
|
PlannerRestrictionContext *
|
||||||
plannerRestrictionContext);
|
plannerRestrictionContext);
|
||||||
static void RemoveFromConversionCandidates(ConversionCandidates *conversionCandidates,
|
|
||||||
int rteIdentity);
|
|
||||||
static bool AllRangeTableEntriesHaveUniqueIndex(List *rangeTableEntryDetailsList);
|
static bool AllRangeTableEntriesHaveUniqueIndex(List *rangeTableEntryDetailsList);
|
||||||
static bool FirstIsSuperSetOfSecond(List *firstIntList, List *secondIntList);
|
static bool FirstIsSuperSetOfSecond(List *firstIntList, List *secondIntList);
|
||||||
|
static void ConvertRTEsToSubquery(List *rangeTableEntryDetailsList,
|
||||||
|
RecursivePlanningContext *context);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RecursivelyPlanLocalTableJoins gets a query and the planner
|
* RecursivelyPlanLocalTableJoins gets a query and the planner
|
||||||
|
@ -192,35 +197,27 @@ RecursivelyPlanLocalTableJoins(Query *query,
|
||||||
CreateConversionCandidates(plannerRestrictionContext,
|
CreateConversionCandidates(plannerRestrictionContext,
|
||||||
rangeTableList, resultRTEIdentity);
|
rangeTableList, resultRTEIdentity);
|
||||||
|
|
||||||
while (ShouldConvertLocalTableJoinsToSubqueries(query, rangeTableList,
|
ConversionChoice conversionChoise =
|
||||||
plannerRestrictionContext))
|
GetConversionChoice(conversionCandidates, plannerRestrictionContext);
|
||||||
{
|
|
||||||
RangeTableEntryDetails *rangeTableEntryDetails =
|
|
||||||
GetNextRTEToConvertToSubquery(conversionCandidates,
|
|
||||||
plannerRestrictionContext);
|
|
||||||
if (rangeTableEntryDetails == NULL)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
RangeTblEntry *rangeTableEntry = rangeTableEntryDetails->rangeTableEntry;
|
if (conversionChoise == CONVERT_LOCAL_TABLES)
|
||||||
List *requiredAttributeNumbers = rangeTableEntryDetails->requiredAttributeNumbers;
|
{
|
||||||
ReplaceRTERelationWithRteSubquery(rangeTableEntry,
|
ConvertRTEsToSubquery(conversionCandidates->localTableList, context);
|
||||||
requiredAttributeNumbers, context);
|
}
|
||||||
int rteIdentity = rangeTableEntryDetails->rteIdentity;
|
else
|
||||||
RemoveFromConversionCandidates(conversionCandidates, rteIdentity);
|
{
|
||||||
|
ConvertRTEsToSubquery(conversionCandidates->distributedTableList, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GetNextRTEToConvertToSubquery returns the range table entry
|
* GetConversionChoice returns the conversion choice considering the local table
|
||||||
* which should be converted to a subquery. It considers the local join policy
|
* join policy.
|
||||||
* for conversion priorities.
|
|
||||||
*/
|
*/
|
||||||
static RangeTableEntryDetails *
|
static ConversionChoice
|
||||||
GetNextRTEToConvertToSubquery(ConversionCandidates *conversionCandidates,
|
GetConversionChoice(ConversionCandidates *conversionCandidates,
|
||||||
PlannerRestrictionContext *plannerRestrictionContext)
|
PlannerRestrictionContext *plannerRestrictionContext)
|
||||||
{
|
{
|
||||||
RangeTableEntryDetails *localRTECandidate = NULL;
|
RangeTableEntryDetails *localRTECandidate = NULL;
|
||||||
RangeTableEntryDetails *distributedRTECandidate = NULL;
|
RangeTableEntryDetails *distributedRTECandidate = NULL;
|
||||||
|
@ -236,11 +233,12 @@ GetNextRTEToConvertToSubquery(ConversionCandidates *conversionCandidates,
|
||||||
|
|
||||||
if (LocalTableJoinPolicy == LOCAL_JOIN_POLICY_PREFER_LOCAL)
|
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)
|
else if (LocalTableJoinPolicy == LOCAL_JOIN_POLICY_PREFER_DISTRIBUTED)
|
||||||
{
|
{
|
||||||
return distributedRTECandidate ? distributedRTECandidate : localRTECandidate;
|
return distributedRTECandidate ? CONVERT_DISTRIBUTED_TABLES :
|
||||||
|
CONVERT_LOCAL_TABLES;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -254,16 +252,35 @@ GetNextRTEToConvertToSubquery(ConversionCandidates *conversionCandidates,
|
||||||
|
|
||||||
if (allRangeTableEntriesHaveUniqueIndex)
|
if (allRangeTableEntriesHaveUniqueIndex)
|
||||||
{
|
{
|
||||||
return distributedRTECandidate ? distributedRTECandidate : localRTECandidate;
|
return distributedRTECandidate ? CONVERT_DISTRIBUTED_TABLES :
|
||||||
|
CONVERT_LOCAL_TABLES;
|
||||||
}
|
}
|
||||||
else
|
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
|
* AllRangeTableEntriesHaveUniqueIndex returns true if all of the RTE's in the given
|
||||||
* list have a unique index.
|
* 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
|
* ShouldConvertLocalTableJoinsToSubqueries returns true if we should
|
||||||
* convert local-dist table joins to subqueries.
|
* convert local-dist table joins to subqueries.
|
||||||
|
@ -506,7 +488,6 @@ CreateConversionCandidates(PlannerRestrictionContext *plannerRestrictionContext,
|
||||||
palloc0(sizeof(RangeTableEntryDetails));
|
palloc0(sizeof(RangeTableEntryDetails));
|
||||||
|
|
||||||
rangeTableEntryDetails->rangeTableEntry = rangeTableEntry;
|
rangeTableEntryDetails->rangeTableEntry = rangeTableEntry;
|
||||||
rangeTableEntryDetails->rteIdentity = rteIdentity;
|
|
||||||
rangeTableEntryDetails->requiredAttributeNumbers =
|
rangeTableEntryDetails->requiredAttributeNumbers =
|
||||||
RequiredAttrNumbersForRelation(rangeTableEntry, plannerRestrictionContext);
|
RequiredAttrNumbersForRelation(rangeTableEntry, plannerRestrictionContext);
|
||||||
rangeTableEntryDetails->hasConstantFilterOnUniqueColumn =
|
rangeTableEntryDetails->hasConstantFilterOnUniqueColumn =
|
||||||
|
|
|
@ -1793,6 +1793,7 @@ TransformFunctionRTE(RangeTblEntry *rangeTblEntry)
|
||||||
subquery->targetList = lappend(subquery->targetList, targetEntry);
|
subquery->targetList = lappend(subquery->targetList, targetEntry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If tupleDesc is NULL we have 2 different cases:
|
* If tupleDesc is NULL we have 2 different cases:
|
||||||
*
|
*
|
||||||
|
@ -1842,6 +1843,7 @@ TransformFunctionRTE(RangeTblEntry *rangeTblEntry)
|
||||||
columnType = list_nth_oid(rangeTblFunction->funccoltypes,
|
columnType = list_nth_oid(rangeTblFunction->funccoltypes,
|
||||||
targetColumnIndex);
|
targetColumnIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* use the types in the function definition otherwise */
|
/* use the types in the function definition otherwise */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue