@@ -75,6 +75,8 @@ static bool try_redistribute(PlannerInfo *root, CdbpathMfjRel *g,
7575
7676static SplitUpdatePath * make_splitupdate_path (PlannerInfo * root , Path * subpath , Index rti );
7777
78+ static SplitMergePath * make_split_merge_path (PlannerInfo * root , Path * subpath , List * resultRelations , List * mergeActionLists );
79+
7880static bool can_elide_explicit_motion (PlannerInfo * root , Index rti , Path * subpath , GpPolicy * policy );
7981/*
8082 * cdbpath_cost_motion
@@ -2774,6 +2776,82 @@ create_split_update_path(PlannerInfo *root, Index rti, GpPolicy *policy, Path *s
27742776 return subpath ;
27752777}
27762778
2779+
2780+ Path *
2781+ create_motion_path_for_merge (PlannerInfo * root , List * resultRelations , GpPolicy * policy , List * mergeActionLists , Path * subpath )
2782+ {
2783+ GpPolicyType policyType = policy -> ptype ;
2784+ CdbPathLocus targetLocus ;
2785+ RelOptInfo * rel ;
2786+ ListCell * lc , * l ;
2787+ bool need_split_merge = false;
2788+
2789+ if (policyType == POLICYTYPE_PARTITIONED )
2790+ {
2791+ /*
2792+ * If merge contain CMD_INSERT, we need split merge to let new
2793+ * insert tuple redistributed to correct segment. otherwise, we
2794+ * create motion as the same as update/delete in create_motion_path_for_upddel
2795+ */
2796+ foreach (l , mergeActionLists )
2797+ {
2798+ List * mergeActionList = lfirst (l );
2799+ foreach (lc , mergeActionList )
2800+ {
2801+ MergeAction * action = lfirst (lc );
2802+ if (action -> commandType == CMD_INSERT )
2803+ need_split_merge = true;
2804+ }
2805+ }
2806+
2807+ if (need_split_merge )
2808+ {
2809+ if (root -> simple_rel_array [linitial_int (resultRelations )])
2810+ rel = root -> simple_rel_array [linitial_int (resultRelations )];
2811+ else
2812+ rel = build_simple_rel (root , linitial_int (resultRelations ), NULL /*parent*/ );
2813+ targetLocus = cdbpathlocus_from_baserel (root , rel , 0 );
2814+
2815+ subpath = (Path * ) make_split_merge_path (root , subpath , resultRelations , mergeActionLists );
2816+ subpath = cdbpath_create_explicit_motion_path (root ,
2817+ subpath ,
2818+ targetLocus );
2819+ }
2820+ else
2821+ {
2822+
2823+ if (can_elide_explicit_motion (root , linitial_int (resultRelations ), subpath , policy ))
2824+ return subpath ;
2825+ else
2826+ {
2827+ CdbPathLocus_MakeStrewn (& targetLocus , policy -> numsegments , 0 );
2828+ subpath = cdbpath_create_explicit_motion_path (root ,
2829+ subpath ,
2830+ targetLocus );
2831+ }
2832+ }
2833+ }
2834+ else if (policyType == POLICYTYPE_ENTRY )
2835+ {
2836+ /* Master-only table */
2837+ CdbPathLocus_MakeEntry (& targetLocus );
2838+ subpath = cdbpath_create_motion_path (root , subpath , NIL , false, targetLocus );
2839+ }
2840+ else if (policyType == POLICYTYPE_REPLICATED )
2841+ {
2842+ /*
2843+ * The statement that insert/update/delete on replicated table has to
2844+ * be dispatched to each segment and executed on each segment. Thus
2845+ * the targetlist cannot contain volatile functions.
2846+ */
2847+ if (contain_volatile_functions ((Node * ) (subpath -> pathtarget -> exprs )))
2848+ elog (ERROR , "could not devise a plan." );
2849+ }
2850+ else
2851+ elog (ERROR , "unrecognized policy type %u" , policyType );
2852+ return subpath ;
2853+ }
2854+
27772855/*
27782856 * turn_volatile_seggen_to_singleqe
27792857 *
@@ -2836,6 +2914,35 @@ turn_volatile_seggen_to_singleqe(PlannerInfo *root, Path *path, Node *node)
28362914 return path ;
28372915}
28382916
2917+ static SplitMergePath *
2918+ make_split_merge_path (PlannerInfo * root , Path * subpath , List * resultRelations , List * mergeActionLists )
2919+ {
2920+ PathTarget * splitMergePathTarget ;
2921+ SplitMergePath * splitmergepath ;
2922+
2923+ splitMergePathTarget = copy_pathtarget (subpath -> pathtarget );
2924+
2925+ /* populate information generated above into splitupdate node */
2926+ splitmergepath = makeNode (SplitMergePath );
2927+ splitmergepath -> path .pathtype = T_SplitMerge ;
2928+ splitmergepath -> path .parent = subpath -> parent ;
2929+ splitmergepath -> path .pathtarget = splitMergePathTarget ;
2930+ splitmergepath -> path .param_info = NULL ;
2931+ splitmergepath -> path .parallel_aware = false;
2932+ splitmergepath -> path .parallel_safe = subpath -> parallel_safe ;
2933+ splitmergepath -> path .parallel_workers = subpath -> parallel_workers ;
2934+ splitmergepath -> path .rows = 2 * subpath -> rows ;
2935+ splitmergepath -> path .startup_cost = subpath -> startup_cost ;
2936+ splitmergepath -> path .total_cost = subpath -> total_cost ;
2937+ splitmergepath -> path .pathkeys = subpath -> pathkeys ;
2938+ splitmergepath -> path .locus = subpath -> locus ;
2939+ splitmergepath -> subpath = subpath ;
2940+ splitmergepath -> resultRelations = resultRelations ;
2941+ splitmergepath -> mergeActionLists = mergeActionLists ;
2942+
2943+ return splitmergepath ;
2944+ }
2945+
28392946static SplitUpdatePath *
28402947make_splitupdate_path (PlannerInfo * root , Path * subpath , Index rti )
28412948{
0 commit comments