提交 0e461e16 编写于 作者: P Pengzhou Tang 提交者: Tang Pengzhou

Fix a bug of replicated table

Previously, when creating join path between CdbLocusType_SingleQE path
and CdbLocusType_SegmentGeneral path, we always add a motion on top
of CdbLocusType_SegmentGeneral path so even the join path is promoted
to executed on QD, the CdbLocusType_SegmentGeneral path can still be
executed to segments.
                     join (CdbLocusType_SingleQE)
					/    \
                   /      \
CdbLocusType_SingleQE     Gather Motion
                            \
                          CdbLocusType_SegmentGeneral

For example:
(select * from partitioned_table limit 1) as t1
Nested Loop
    ->  Gather Motion 1:1
	     ->  Seq Scan on replicated_table
    ->  Materialize
		 ->  Subquery Scan on t1
		    ->  Limit
			   ->  Gather Motion 3:1
	               ->  Limit
		               ->  Seq Scan on partitioned_table
replicated_table only store tuples on segments, so without
the gather motion, seq scan of replicated_table doesn't
provide tuples.

There is another problem, if join path is not promoted to
QD, the gather motion might be redundant, For example:

  (select * from replicated_table, (select * from
  partitioned_table limit 1) t1) sub1;

Gather Motion 3:1
  -> Nested Loop
      ->  Seq Scan on partitioned_table_2
      ->  Materialize
          ->  Broadcast Motion 1:3
              -> Nested Loop
                 ->  Gather Motion 1:1 (redundant motion)
	                 ->  Seq Scan on replicated_table
              ->  Materialize
		         ->  Subquery Scan on t1
		            ->  Limit
			             ->  Gather Motion 3:1
	                       ->  Limit
		                      ->  Seq Scan on partitioned_table

So in apply_motion_mutator(), we omit such redundant motion if
it's not gathered to top slice (QD). sliceDepth == 0 means it
is top slice, however, sliceDepth now is shared by both init
plans and main plan, so if main plan increased the sliceDepth,
init plan may omit the gather motion unexpectedly which create
a wrong results.

The fix is simple to reset sliceDepth for init plans
上级 64cdd47c
......@@ -675,10 +675,14 @@ apply_motion_mutator(Node *node, ApplyMotionState *context)
if (IsA(node, SubPlan) &&((SubPlan *) node)->is_initplan)
{
bool saveContainMotionNodes = context->containMotionNodes;
int saveSliceDepth = context->sliceDepth;
/* reset sliceDepth for each init plan */
context->sliceDepth = 0;
node = plan_tree_mutator(node, apply_motion_mutator, context);
context->containMotionNodes = saveContainMotionNodes;
context->sliceDepth = saveSliceDepth;
return node;
}
......
......@@ -535,6 +535,15 @@ select * from foo;
---+---
(0 rows)
-- Test replicate table within init plan
insert into foo values (1, 1), (2, 1);
select * from bar where exists (select * from foo);
x | y
---+---
2 | 2
1 | 2
(2 rows)
drop schema rpt cascade;
NOTICE: drop cascades to 2 other objects
DETAIL: drop cascades to table foo
......
......@@ -267,4 +267,8 @@ select * from foo;
delete from foo where y = 1;
select * from foo;
-- Test replicate table within init plan
insert into foo values (1, 1), (2, 1);
select * from bar where exists (select * from foo);
drop schema rpt cascade;
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册