@@ -125,6 +125,10 @@ static void multicorn_xact_callback(XactEvent event, void *arg);
125125void * serializePlanState (MulticornPlanState * planstate );
126126MulticornExecState * initializeExecState (void * internal_plan_state );
127127
128+ static void add_foreign_ordered_paths (PlannerInfo * root ,
129+ RelOptInfo * input_rel ,
130+ RelOptInfo * final_rel ,
131+ FinalPathExtraData * extra );
128132static void add_foreign_final_paths (PlannerInfo * root ,
129133 RelOptInfo * input_rel ,
130134 RelOptInfo * final_rel ,
@@ -454,8 +458,20 @@ static void multicornGetForeignUpperPaths(PlannerInfo *root,
454458 RelOptInfo * output_rel ,
455459 void * extra )
456460{
461+ // elog(WARNING, "Got input_rel private: %p", input_rel->fdw_private);
462+ // elog(WARNING, "Got output_rel private: %p", output_rel->fdw_private);
463+
464+ // If the input_rel has no private, then pushdown wasn't supported for the previous stage
465+ // Which means we can't pushdown anything for the the current stage (as least this is true for limit/offset)
466+ if (!input_rel -> fdw_private )
467+ return ;
468+
469+ // elog(WARNING, "Got stage: %d", stage);
457470 switch (stage )
458471 {
472+ case UPPERREL_ORDERED :
473+ add_foreign_ordered_paths (root , input_rel , output_rel , (FinalPathExtraData * )extra );
474+ break ;
459475 case UPPERREL_FINAL :
460476 add_foreign_final_paths (root , input_rel , output_rel , (FinalPathExtraData * )extra );
461477 break ;
@@ -464,6 +480,60 @@ static void multicornGetForeignUpperPaths(PlannerInfo *root,
464480 }
465481}
466482
483+ /*
484+ * add_foreign_ordered_paths
485+ * Add foreign paths for performing the sort processing remotely.
486+ *
487+ * Given input_rel contains the source-data Paths. The paths are added to the
488+ * given final_rel.
489+ *
490+ * Note: Since sorts are already taken care of in the base rel, we only check for pushdown here.
491+ */
492+ static void
493+ add_foreign_ordered_paths (PlannerInfo * root , RelOptInfo * input_rel ,
494+ RelOptInfo * final_rel ,
495+ FinalPathExtraData * extra )
496+ {
497+ List * applied_pathkeys = NIL ;
498+ ListCell * lc ;
499+ MulticornPlanState * planstate = input_rel -> fdw_private ;
500+ ForeignPath * cheapest_path = (ForeignPath * )input_rel -> cheapest_total_path ;
501+ if ( planstate )
502+ {
503+ if (cheapest_path && IsA (cheapest_path , ForeignPath ))
504+ {
505+ MulticornPathState * pathstate = (MulticornPathState * )cheapest_path -> fdw_private ;
506+ if ( pathstate )
507+ {
508+ planstate -> pathkeys = pathstate -> pathkeys ;
509+ }
510+ }
511+
512+ /* Extract the pathkeys from the input_rel */
513+ foreach (lc , input_rel -> pathlist )
514+ {
515+ Path * path = (Path * ) lfirst (lc );
516+ if (IsA (path , ForeignPath ))
517+ {
518+ ForeignPath * fpath = (ForeignPath * ) path ;
519+ if (fpath -> path .pathkeys != NIL )
520+ {
521+ applied_pathkeys = fpath -> path .pathkeys ;
522+ break ;
523+ }
524+ }
525+ }
526+
527+ /* We only support limit/offset if the sort is completely pushed down */
528+ /* By bailing here, input_rel for the next state will not have planstate, which will cause no more pushdowns */
529+ if (!pathkeys_contained_in (root -> sort_pathkeys , applied_pathkeys ))
530+ return ;
531+
532+ planstate -> input_rel = input_rel ;
533+ final_rel -> fdw_private = planstate ;
534+ }
535+ }
536+
467537/*
468538 * add_foreign_final_paths
469539 * Add foreign paths for performing the final processing remotely.
@@ -482,10 +552,6 @@ static void multicornGetForeignUpperPaths(PlannerInfo *root,
482552 ForeignPath * final_path ;
483553 int limitCount = -1 ;
484554 int limitOffset = -1 ;
485- Path * cheapest_path ;
486- List * deparsed_pathkeys = NIL ;
487- List * applied_pathkeys = NIL ;
488- ListCell * lc ;
489555
490556 /* No work if there is no need to add a LIMIT node */
491557 if (!extra -> limit_needed )
@@ -499,6 +565,10 @@ static void multicornGetForeignUpperPaths(PlannerInfo *root,
499565 if (parse -> limitOption == LIMIT_OPTION_WITH_TIES )
500566 return ;
501567
568+ /* We don't currently support pushing down limits with quals */
569+ if (parse -> jointree -> quals )
570+ return ;
571+
502572 /* only push down constant LIMITs... */
503573 if ((parse -> limitCount && !IsA (parse -> limitCount , Const )) || (parse -> limitOffset && !IsA (parse -> limitOffset , Const )))
504574 return ;
@@ -516,57 +586,16 @@ static void multicornGetForeignUpperPaths(PlannerInfo *root,
516586
517587 /* Get the current input_rel and it's planstate */
518588 planstate = input_rel -> fdw_private ;
519- // TODO: Maybe this isn't needed if we handle the previous stages correctly?
520- if (!planstate )
521- {
522- for (int i = 1 ; i < root -> simple_rel_array_size ; i ++ )
523- {
524- RelOptInfo * rel = root -> simple_rel_array [i ];
525- if (rel && rel -> reloptkind == RELOPT_BASEREL )
526- {
527- planstate = rel -> fdw_private ;
528- input_rel -> fdw_private = planstate ;
529- input_rel = rel ;
530- break ;
531- }
532- }
533- }
534-
535- /* Extract pathkeys from the cheapest path's fdw_private if it exists */
536- cheapest_path = input_rel -> cheapest_total_path ;
537- if (cheapest_path && IsA (cheapest_path , ForeignPath ))
538- {
539- ForeignPath * foreign_path = (ForeignPath * )cheapest_path ;
540- if (foreign_path -> fdw_private )
541- {
542- MulticornPathState * input_pathstate = (MulticornPathState * )foreign_path -> fdw_private ;
543- deparsed_pathkeys = input_pathstate -> pathkeys ;
544- }
545- }
546-
547- /* Extract the pathkeys from the input_rel */
548- foreach (lc , input_rel -> pathlist )
549- {
550- Path * path = (Path * ) lfirst (lc );
551- if (IsA (path , ForeignPath ))
552- {
553- ForeignPath * fpath = (ForeignPath * ) path ;
554- if (fpath -> path .pathkeys != NIL )
555- applied_pathkeys = fpath -> path .pathkeys ;
556- }
557- }
558-
559- /* We only support limit/offset if the sort is completely pushed down */
560- if (!pathkeys_contained_in (root -> sort_pathkeys , applied_pathkeys ))
561- return ;
589+ if ( planstate -> input_rel )
590+ input_rel = planstate -> input_rel ;
562591
563592 /* Check if Python FWD can push down the LIMIT/OFFSET */
564593 if (!canLimit (planstate , limitCount , limitOffset ))
565594 return ;
566595
567596 /* Create foreign final path with the correct number of rows, and include state for limit/offset pushdown */
568597 pathstate = (MulticornPathState * )calloc (1 , sizeof (MulticornPathState ));
569- pathstate -> pathkeys = deparsed_pathkeys ;
598+ pathstate -> pathkeys = planstate -> pathkeys ;
570599 pathstate -> limit = limitCount ;
571600 pathstate -> offset = limitOffset ;
572601 final_path = create_foreign_upper_path (root ,
0 commit comments