Refactor distributed planner functions to improve readability and remove unused code

issue_7882_main_2
Mehmet Yilmaz 2025-03-24 15:56:47 +00:00
parent c4ccb10f09
commit 5b032bb6a0
1 changed files with 49 additions and 128 deletions

View File

@ -154,11 +154,6 @@ static bool CheckPostPlanDistribution(bool isDistributedQuery,
Query *origQuery, Query *origQuery,
List *rangeTableList, List *rangeTableList,
Query *plannedQuery); Query *plannedQuery);
static bool
ListContainsDistributedTableRTERecursive(Query *outerQuery, List *rangeTableList,
bool *maybeHasForeignDistributedTable);
static Query *
FindCTEQueryByName(Query *outerQuery, const char *cteName);
/* Distributed planner hook */ /* Distributed planner hook */
PlannedStmt * PlannedStmt *
@ -361,144 +356,70 @@ ExtractRangeTableEntryList(Query *query)
bool bool
NeedsDistributedPlanning(Query *query) NeedsDistributedPlanning(Query *query)
{ {
if (!CitusHasBeenLoaded()) if (!CitusHasBeenLoaded())
return false; {
return false;
}
CmdType commandType = query->commandType; CmdType commandType = query->commandType;
if (commandType != CMD_SELECT && commandType != CMD_INSERT &&
commandType != CMD_UPDATE && commandType != CMD_DELETE)
return false;
List *allRTEs = ExtractRangeTableEntryList(query); if (commandType != CMD_SELECT && commandType != CMD_INSERT &&
return ListContainsDistributedTableRTE(allRTEs, NULL); commandType != CMD_UPDATE && commandType != CMD_DELETE)
{
return false;
}
List *allRTEs = ExtractRangeTableEntryList(query);
return ListContainsDistributedTableRTE(allRTEs, NULL);
} }
/* /*
* Wrapper for top-level calls. * ListContainsDistributedTableRTE gets a list of range table entries
* and returns true if there is at least one distributed relation range
* table entry in the list. The boolean maybeHasForeignDistributedTable
* variable is set to true if the list contains a foreign table.
*/ */
bool bool
ListContainsDistributedTableRTE(List *rangeTableList, bool *maybeHasForeignDistributedTable) ListContainsDistributedTableRTE(List *rangeTableList,
bool *maybeHasForeignDistributedTable)
{ {
return ListContainsDistributedTableRTERecursive(NULL, rangeTableList, maybeHasForeignDistributedTable); ListCell *rangeTableCell = NULL;
}
foreach(rangeTableCell, rangeTableList)
{
RangeTblEntry *rangeTableEntry = (RangeTblEntry *) lfirst(rangeTableCell);
/* if (rangeTableEntry->rtekind != RTE_RELATION)
* FindCTEQueryByName {
* continue;
* Given an outer query and a CTE name, returns the corresponding }
* CTE's query definition from outerQuery->cteList, or NULL if not found.
* (In PG17, ctelevelsup is removed so we match only on cte name.)
*/
static Query *
FindCTEQueryByName(Query *outerQuery, const char *cteName)
{
ListCell *lc;
foreach(lc, outerQuery->cteList)
{
CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
if (strcmp(cte->ctename, cteName) == 0)
{
return (Query *) cte->ctequery;
}
}
return NULL;
}
/* if (HideCitusDependentObjects && IsolationIsSerializable() && IsPgLocksTable(
* ListContainsDistributedTableRTERecursive rangeTableEntry))
* {
* Recursively checks the given range table list for an RTE that represents a /*
* distributed table. For RTE_SUBQUERY and RTE_CTE, it extracts all RTEs from the * Postgres tidscan.sql test fails if we do not filter pg_locks table because
* subquery (or CTE definition, if the subquery pointer is NULL) and recurses. * test results, which show taken locks in serializable isolation mode,
* * fails by showing extra lock taken by IsCitusTable below.
* The outerQuery parameter is the top-level query; it is used to look up CTE */
* definitions if an RTE_CTE does not have its subquery pointer set. continue;
*/ }
static bool
ListContainsDistributedTableRTERecursive(Query *outerQuery, List *rangeTableList,
bool *maybeHasForeignDistributedTable)
{
ListCell *rangeTableCell = NULL;
foreach(rangeTableCell, rangeTableList) if (IsCitusTable(rangeTableEntry->relid))
{ {
RangeTblEntry *rte = (RangeTblEntry *) lfirst(rangeTableCell); if (maybeHasForeignDistributedTable != NULL &&
IsForeignTable(rangeTableEntry->relid))
{
*maybeHasForeignDistributedTable = true;
}
/* For base relations, check as before */ return true;
if (rte->rtekind == RTE_RELATION) }
{ }
if (HideCitusDependentObjects &&
IsolationIsSerializable() &&
IsPgLocksTable(rte))
{
continue;
}
if (IsCitusTable(rte->relid))
{
if (maybeHasForeignDistributedTable != NULL &&
IsForeignTable(rte->relid))
{
*maybeHasForeignDistributedTable = true;
}
return true;
}
}
/* For subqueries, check their internal range table */
else if (rte->rtekind == RTE_SUBQUERY)
{
Query *subquery = rte->subquery;
if (subquery != NULL)
{
List *allRTEs = ExtractRangeTableEntryList(subquery);
if (ListContainsDistributedTableRTERecursive(outerQuery, allRTEs,
maybeHasForeignDistributedTable))
{
return true;
}
/* Also check any CTEs defined inside the subquery */
if (subquery->cteList)
{
ListCell *cteCell;
foreach(cteCell, subquery->cteList)
{
CommonTableExpr *cte = (CommonTableExpr *) lfirst(cteCell);
if (cte && cte->ctequery)
{
List *cteRTEs = ExtractRangeTableEntryList((Query *) cte->ctequery);
if (ListContainsDistributedTableRTERecursive(outerQuery, cteRTEs,
maybeHasForeignDistributedTable))
{
return true;
}
}
}
}
}
}
/* For CTE entries, if rte->subquery is NULL then look up its definition */
else if (rte->rtekind == RTE_CTE)
{
Query *cteQuery = rte->subquery;
if (cteQuery == NULL && outerQuery != NULL)
{
cteQuery = FindCTEQueryByName(outerQuery, rte->ctename);
}
if (cteQuery != NULL)
{
List *cteRTEs = ExtractRangeTableEntryList(cteQuery);
if (ListContainsDistributedTableRTERecursive(outerQuery, cteRTEs,
maybeHasForeignDistributedTable))
{
return true;
}
}
}
/* Optionally: handle other RTE kinds if necessary */
}
return false; return false;
} }