@@ -81,8 +81,8 @@ typedef struct PgFdwScanState
81
81
Portal portal ; /* SPI portal */
82
82
int numParams ; /* number of parameters passed to query */
83
83
int tile_pos ;
84
+ uint64 table_pos ;
84
85
HeapTuple spi_tuple ;
85
- SPITupleTable * spi_tuptable ;
86
86
Datum * src_values ;
87
87
Datum * dst_values ;
88
88
bool * src_nulls ;
@@ -629,9 +629,13 @@ postgresIterateForeignScan(ForeignScanState *node)
629
629
MemoryContext oldcontext = MemoryContextSwitchTo (fsstate -> spi_context );
630
630
631
631
while (true) {
632
- if (fsstate -> spi_tuptable == NULL ) {
633
- SPI_cursor_fetch (fsstate -> portal , true, 1 );
634
- if (!SPI_processed ) {
632
+ if (fsstate -> spi_tuple == NULL ) {
633
+ if (fsstate -> portal != NULL ) {
634
+ filter_mask = ~0 ;
635
+ SPI_cursor_fetch (fsstate -> portal , true, 1 );
636
+ fsstate -> table_pos = 0 ;
637
+ }
638
+ if (fsstate -> table_pos == SPI_processed ) {
635
639
MemoryContextSwitchTo (oldcontext );
636
640
return ExecClearTuple (slot );
637
641
}
@@ -642,8 +646,7 @@ postgresIterateForeignScan(ForeignScanState *node)
642
646
fsstate -> tile_pos = 0 ;
643
647
fsstate -> filter_mask = filter_mask ;
644
648
}
645
- fsstate -> spi_tuptable = SPI_tuptable ;
646
- fsstate -> spi_tuple = SPI_tuptable -> vals [0 ];
649
+ fsstate -> spi_tuple = SPI_tuptable -> vals [fsstate -> table_pos ++ ];
647
650
if (fsstate -> vops_types == NULL ) {
648
651
fsstate -> vops_types = palloc (sizeof (vops_type_info )* n_attrs );
649
652
fsstate -> attr_types = palloc (sizeof (Oid )* n_attrs );
@@ -672,7 +675,7 @@ postgresIterateForeignScan(ForeignScanState *node)
672
675
if (i > 0 )
673
676
{
674
677
/* ordinary column */
675
- fsstate -> src_values [i - 1 ] = SPI_getbinval (fsstate -> spi_tuple , fsstate -> spi_tuptable -> tupdesc , j + 1 , & fsstate -> src_nulls [i - 1 ]);
678
+ fsstate -> src_values [i - 1 ] = SPI_getbinval (fsstate -> spi_tuple , SPI_tuptable -> tupdesc , j + 1 , & fsstate -> src_nulls [i - 1 ]);
676
679
}
677
680
j += 1 ;
678
681
}
@@ -742,8 +745,10 @@ postgresIterateForeignScan(ForeignScanState *node)
742
745
NextTuple :;
743
746
}
744
747
SPI_freetuple (fsstate -> spi_tuple );
745
- SPI_freetuptable (fsstate -> spi_tuptable );
746
- fsstate -> spi_tuptable = NULL ;
748
+ if (fsstate -> portal ) {
749
+ SPI_freetuptable (SPI_tuptable );
750
+ }
751
+ fsstate -> spi_tuple = NULL ;
747
752
}
748
753
}
749
754
@@ -760,6 +765,8 @@ postgresReScanForeignScan(ForeignScanState *node)
760
765
bool * nulls = NULL ;
761
766
MemoryContext oldcontext = MemoryContextSwitchTo (fsstate -> spi_context );
762
767
Oid * argtypes = NULL ;
768
+ int rc ;
769
+
763
770
if (fsstate -> numParams > 0 ) {
764
771
ExprContext * econtext = node -> ss .ps .ps_ExprContext ;
765
772
ForeignScan * fsplan = (ForeignScan * ) node -> ss .ps .plan ;
@@ -780,8 +787,17 @@ postgresReScanForeignScan(ForeignScanState *node)
780
787
i += 1 ;
781
788
}
782
789
}
783
- fsstate -> portal = SPI_cursor_open_with_args (NULL , fsstate -> query , fsstate -> numParams , argtypes , values , nulls , true, CURSOR_OPT_PARALLEL_OK );
784
- fsstate -> spi_tuptable = NULL ;
790
+ if (fsstate -> rel == NULL ) { /* aggregate is pushed down: do not use cusror to allow parallel query execution */
791
+ rc = SPI_execute_with_args (fsstate -> query , fsstate -> numParams , argtypes , values , nulls , true, 0 );
792
+ if (rc != SPI_OK_SELECT ) {
793
+ elog (ERROR , "Failed to execute VOPS query %s: %d" , fsstate -> query , rc );
794
+ }
795
+ fsstate -> portal = NULL ;
796
+ } else {
797
+ fsstate -> portal = SPI_cursor_open_with_args (NULL , fsstate -> query , fsstate -> numParams , argtypes , values , nulls , true, CURSOR_OPT_PARALLEL_OK );
798
+ }
799
+ fsstate -> table_pos = 0 ;
800
+ fsstate -> spi_tuple = NULL ;
785
801
786
802
MemoryContextSwitchTo (oldcontext );
787
803
}
@@ -800,7 +816,9 @@ postgresEndForeignScan(ForeignScanState *node)
800
816
{
801
817
MemoryContext oldcontext = MemoryContextSwitchTo (fsstate -> spi_context );
802
818
803
- SPI_cursor_close (fsstate -> portal );
819
+ if (fsstate -> portal ) {
820
+ SPI_cursor_close (fsstate -> portal );
821
+ }
804
822
SPI_finish ();
805
823
806
824
MemoryContextSwitchTo (oldcontext );
0 commit comments