Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 36 additions & 3 deletions src/backend/distributed/planner/local_distributed_join_planner.c
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,8 @@ AppendUniqueIndexColumnsToList(Form_pg_index indexForm, List **uniqueIndexGroups
*/
List *
RequiredAttrNumbersForRelation(RangeTblEntry *rangeTableEntry,
PlannerRestrictionContext *plannerRestrictionContext)
PlannerRestrictionContext *plannerRestrictionContext,
int originalRteIndex)
{
RelationRestriction *relationRestriction =
RelationRestrictionForRelation(rangeTableEntry, plannerRestrictionContext);
Expand All @@ -498,7 +499,35 @@ RequiredAttrNumbersForRelation(RangeTblEntry *rangeTableEntry,
*/
Query *queryToProcess = plannerInfo->parse;

return RequiredAttrNumbersForRelationInternal(queryToProcess, rteIndex);
List *result = RequiredAttrNumbersForRelationInternal(queryToProcess, rteIndex);

/*
* When PostgreSQL expands inheritance tables, expand_single_inheritance_child()
* copies the parent RTE via memcpy, which duplicates Citus's identity marker
* (values_lists). This can cause RelationRestrictionForRelation() to return a
* restriction for a child RTE whose index differs from the original parent
* position. Since Vars in plannerInfo->parse still reference the parent's
* original position, we must also search at originalRteIndex to find them.
*/
if (originalRteIndex > 0 && originalRteIndex != rteIndex)
{
List *additional = RequiredAttrNumbersForRelationInternal(queryToProcess,
originalRteIndex);
#if PG_VERSION_NUM >= 170000
foreach_int(attrNo, additional)
{
result = list_append_unique_int(result, attrNo);
}
#else
ListCell *lc;
foreach(lc, additional)
{
result = list_append_unique_int(result, lfirst_int(lc));
}
#endif
}

return result;
}


Expand Down Expand Up @@ -541,9 +570,12 @@ CreateConversionCandidates(PlannerRestrictionContext *plannerRestrictionContext,
palloc0(sizeof(ConversionCandidates));


int rangeTableIndex = 0;
RangeTblEntry *rangeTableEntry = NULL;
foreach_declared_ptr(rangeTableEntry, rangeTableList)
{
rangeTableIndex++;

/* we're only interested in tables */
if (!IsRecursivelyPlannableRelation(rangeTableEntry))
{
Expand All @@ -566,7 +598,8 @@ CreateConversionCandidates(PlannerRestrictionContext *plannerRestrictionContext,

rangeTableEntryDetails->rangeTableEntry = rangeTableEntry;
rangeTableEntryDetails->requiredAttributeNumbers =
RequiredAttrNumbersForRelation(rangeTableEntry, plannerRestrictionContext);
RequiredAttrNumbersForRelation(rangeTableEntry, plannerRestrictionContext,
rangeTableIndex);
rangeTableEntryDetails->hasConstantFilterOnUniqueColumn =
HasConstantFilterOnUniqueColumn(rangeTableEntry, relationRestriction);
rangeTableEntryDetails->perminfo = NULL;
Expand Down
3 changes: 2 additions & 1 deletion src/backend/distributed/planner/recursive_planning.c
Original file line number Diff line number Diff line change
Expand Up @@ -971,7 +971,8 @@ RecursivelyPlanDistributedJoinNode(Node *node, Query *query,
PlannerRestrictionContext *restrictionContext =
GetPlannerRestrictionContext(recursivePlanningContext);
List *requiredAttributes =
RequiredAttrNumbersForRelation(distributedRte, restrictionContext);
RequiredAttrNumbersForRelation(distributedRte, restrictionContext,
rangeTableRef->rtindex);

RTEPermissionInfo *perminfo = NULL;
if (distributedRte->perminfoindex)
Expand Down
3 changes: 2 additions & 1 deletion src/include/distributed/local_distributed_join_planner.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ extern void RecursivelyPlanLocalTableJoins(Query *query,
RecursivePlanningContext *context);
extern List * RequiredAttrNumbersForRelation(RangeTblEntry *relationRte,
PlannerRestrictionContext *
plannerRestrictionContext);
plannerRestrictionContext,
int originalRteIndex);
extern List * RequiredAttrNumbersForRelationInternal(Query *queryToProcess, int rteIndex);

#endif /* LOCAL_DISTRIBUTED_JOIN_PLANNER_H */
32 changes: 32 additions & 0 deletions src/test/regress/expected/local_dist_join.out
Original file line number Diff line number Diff line change
Expand Up @@ -887,3 +887,35 @@ SELECT COUNT(DISTINCT name) FROM distributed;
(1 row)

ROLLBACK;
-- Test for inheritance parent column in WHERE with LEFT JOIN ON FALSE
-- Regression test for https://github.com/citusdata/citus/issues/8553
-- When a local inheritance parent table is cross-joined with a distributed
-- table through LEFT JOIN ... ON FALSE, a WHERE clause on the parent column
-- should not incorrectly drop all rows.
SET citus.use_citus_managed_tables TO off;
CREATE TABLE inh_parent(c0 REAL);
CREATE TABLE inh_child(c1 INT) INHERITS (inh_parent);
RESET citus.use_citus_managed_tables;
INSERT INTO inh_child VALUES (1.0, 1);
-- This query should return 101 rows (1 child row x 101 distributed rows)
SELECT count(*) FROM distributed, inh_child LEFT JOIN inh_parent ON FALSE WHERE inh_child.c0 IS NOT NULL;
count
---------------------------------------------------------------------
101
(1 row)

-- Additional variations to test the same pattern
SELECT count(*) FROM distributed, inh_child LEFT JOIN inh_parent ON FALSE WHERE inh_child.c0 = 1;
count
---------------------------------------------------------------------
101
(1 row)

SELECT count(*) FROM distributed, inh_child LEFT JOIN inh_parent ON FALSE;
count
---------------------------------------------------------------------
101
(1 row)

DROP TABLE inh_child;
DROP TABLE inh_parent;
21 changes: 21 additions & 0 deletions src/test/regress/sql/local_dist_join.sql
Original file line number Diff line number Diff line change
Expand Up @@ -341,3 +341,24 @@ WHERE
distributed.id = local.id;
SELECT COUNT(DISTINCT name) FROM distributed;
ROLLBACK;

-- Test for inheritance parent column in WHERE with LEFT JOIN ON FALSE
-- Regression test for https://github.com/citusdata/citus/issues/8553
-- When a local inheritance parent table is cross-joined with a distributed
-- table through LEFT JOIN ... ON FALSE, a WHERE clause on the parent column
-- should not incorrectly drop all rows.
SET citus.use_citus_managed_tables TO off;
CREATE TABLE inh_parent(c0 REAL);
CREATE TABLE inh_child(c1 INT) INHERITS (inh_parent);
RESET citus.use_citus_managed_tables;
INSERT INTO inh_child VALUES (1.0, 1);

-- This query should return 101 rows (1 child row x 101 distributed rows)
SELECT count(*) FROM distributed, inh_child LEFT JOIN inh_parent ON FALSE WHERE inh_child.c0 IS NOT NULL;

-- Additional variations to test the same pattern
SELECT count(*) FROM distributed, inh_child LEFT JOIN inh_parent ON FALSE WHERE inh_child.c0 = 1;
SELECT count(*) FROM distributed, inh_child LEFT JOIN inh_parent ON FALSE;

DROP TABLE inh_child;
DROP TABLE inh_parent;
Loading