@@ -53,7 +53,6 @@ typedef struct
5353
5454Datum * values ;
5555bool * nulls ;
56- HeapTuple stored_tuple ;
5756
5857List * scan_tlist ;
5958
@@ -450,8 +449,9 @@ create_crossmatch_plan(PlannerInfo *root,
450449cscan -> scan .plan .targetlist = tlist ;
451450cscan -> scan .plan .qual = joinclauses ;
452451cscan -> scan .scanrelid = 0 ;
453- cscan -> custom_scan_tlist = make_tlist_from_pathtarget (& rel -> reltarget );/* tlist of the 'virtual' join rel
454- we'll have to build and scan */
452+
453+ /* tlist of the 'virtual' join rel we'll have to build and scan */
454+ cscan -> custom_scan_tlist = make_tlist_from_pathtarget (& rel -> reltarget );
455455
456456cscan -> flags = best_path -> flags ;
457457cscan -> methods = & crossmatch_plan_methods ;
@@ -520,100 +520,113 @@ crossmatch_begin(CustomScanState *node, EState *estate, int eflags)
520520if (scan_state -> scan_tlist == NIL )
521521{
522522TupleDesc tupdesc = node -> ss .ss_ScanTupleSlot -> tts_tupleDescriptor ;
523- scan_state -> stored_tuple = heap_form_tuple (tupdesc ,NULL ,NULL );
523+
524+ ExecStoreTuple (heap_form_tuple (tupdesc ,NULL ,NULL ),
525+ node -> ss .ss_ScanTupleSlot ,
526+ InvalidBuffer ,
527+ false);
524528}
525- else
526- scan_state -> stored_tuple = NULL ;
527529}
528530
529- static TupleTableSlot *
530- crossmatch_exec ( CustomScanState * node )
531+ static bool
532+ fetch_next_pair ( CrossmatchScanState * scan_state )
531533{
532- CrossmatchScanState * scan_state = ( CrossmatchScanState * ) node ;
533- TupleTableSlot * scanSlot = node -> ss . ss_ScanTupleSlot ;
534- HeapTuple htup = scan_state -> stored_tuple ;
534+ ScanState * ss = & scan_state -> css . ss ;
535+ TupleTableSlot * slot = ss -> ss_ScanTupleSlot ;
536+ TupleDesc tupdesc = ss -> ss_ScanTupleSlot -> tts_tupleDescriptor ;
535537
536- for (;;)
538+ HeapTuple htup ;
539+ Datum * values = scan_state -> values ;
540+ bool * nulls = scan_state -> nulls ;
541+
542+ ItemPointerData p_tids [2 ]= {0 };
543+ HeapTupleData htup_outer ;
544+ HeapTupleData htup_inner ;
545+ Buffer buf1 ;
546+ Buffer buf2 ;
547+
548+ crossmatch (scan_state -> ctx ,p_tids );
549+
550+ if (!ItemPointerIsValid (& p_tids [0 ])|| !ItemPointerIsValid (& p_tids [1 ]))
537551{
538- /* Fetch next tid pair */
539- if (!node -> ss .ps .ps_TupFromTlist )
540- {
541- Datum * values = scan_state -> values ;
542- bool * nulls = scan_state -> nulls ;
552+ return false;
553+ }
543554
544- ItemPointerData p_tids [2 ]= {0 };
545- HeapTupleData htup_outer ;
546- HeapTupleData htup_inner ;
547- Buffer buf1 ;
548- Buffer buf2 ;
555+ /* We don't have to fetch tuples if scan tlist is empty */
556+ if (scan_state -> scan_tlist != NIL )
557+ {
558+ bool htup_outer_ready = false;
559+ bool htup_inner_ready = false;
560+ int col_index = 0 ;
561+ ListCell * l ;
549562
550- crossmatch (scan_state -> ctx ,p_tids );
563+ htup_outer .t_self = p_tids [0 ];
564+ htup_inner .t_self = p_tids [1 ];
565+
566+ foreach (l ,scan_state -> scan_tlist )
567+ {
568+ TargetEntry * target = (TargetEntry * )lfirst (l );
569+ Var * var = (Var * )target -> expr ;
551570
552- if (! ItemPointerIsValid ( & p_tids [ 0 ]) || ! ItemPointerIsValid ( & p_tids [ 1 ]) )
571+ if (var -> varno == scan_state -> outer_relid )
553572{
554- return ExecClearTuple (node -> ss .ps .ps_ResultTupleSlot );
573+ if (!htup_outer_ready )
574+ {
575+ htup_outer_ready = true;
576+ /* TODO: check result */
577+ heap_fetch (scan_state -> outer ,SnapshotSelf ,
578+ & htup_outer ,& buf1 , false,NULL );
579+ }
580+
581+ values [col_index ]= heap_getattr (& htup_outer ,var -> varattno ,
582+ scan_state -> outer -> rd_att ,
583+ & nulls [col_index ]);
555584}
556585
557- /* We don't have to fetch tuples if scan tlist is empty */
558- if (scan_state -> scan_tlist != NIL )
586+ if (var -> varno == scan_state -> inner_relid )
559587{
560- TupleDesc tupdesc = node -> ss .ss_ScanTupleSlot -> tts_tupleDescriptor ;
561- bool htup_outer_ready = false;
562- bool htup_inner_ready = false;
563- int col_index = 0 ;
564- ListCell * l ;
588+ if (!htup_inner_ready )
589+ {
590+ htup_inner_ready = true;
591+ heap_fetch (scan_state -> inner ,SnapshotSelf ,
592+ & htup_inner ,& buf2 , false,NULL );
593+ }
565594
566- htup_outer .t_self = p_tids [0 ];
567- htup_inner .t_self = p_tids [1 ];
595+ values [col_index ]= heap_getattr (& htup_inner ,var -> varattno ,
596+ scan_state -> outer -> rd_att ,
597+ & nulls [col_index ]);
598+ }
568599
569- foreach (l ,scan_state -> scan_tlist )
570- {
571- TargetEntry * target = (TargetEntry * )lfirst (l );
572- Var * var = (Var * )target -> expr ;
600+ col_index ++ ;
601+ }
573602
574- if (var -> varno == scan_state -> outer_relid )
575- {
576- if (!htup_outer_ready )
577- {
578- htup_outer_ready = true;
579- /* TODO: check result */
580- heap_fetch (scan_state -> outer ,SnapshotSelf ,
581- & htup_outer ,& buf1 , false,NULL );
582- }
583-
584- values [col_index ]= heap_getattr (& htup_outer ,var -> varattno ,
585- scan_state -> outer -> rd_att ,
586- & nulls [col_index ]);
587- }
603+ if (htup_outer_ready )
604+ ReleaseBuffer (buf1 );
605+ if (htup_inner_ready )
606+ ReleaseBuffer (buf2 );
588607
589- if (var -> varno == scan_state -> inner_relid )
590- {
591- if (!htup_inner_ready )
592- {
593- htup_inner_ready = true;
594- heap_fetch (scan_state -> inner ,SnapshotSelf ,
595- & htup_inner ,& buf2 , false,NULL );
596- }
597-
598- values [col_index ]= heap_getattr (& htup_inner ,var -> varattno ,
599- scan_state -> outer -> rd_att ,
600- & nulls [col_index ]);
601- }
608+ htup = heap_form_tuple (tupdesc ,values ,nulls );
602609
603- col_index ++ ;
604- }
610+ /* Fill scanSlot with a new tuple */
611+ ExecStoreTuple (htup ,slot ,InvalidBuffer , false);
612+ }
605613
606- if (htup_outer_ready )
607- ReleaseBuffer (buf1 );
608- if (htup_inner_ready )
609- ReleaseBuffer (buf2 );
614+ return true;
615+ }
610616
611- htup = heap_form_tuple (tupdesc ,values ,nulls );
612- scan_state -> stored_tuple = htup ;
617+ static TupleTableSlot *
618+ crossmatch_exec (CustomScanState * node )
619+ {
620+ CrossmatchScanState * scan_state = (CrossmatchScanState * )node ;
621+ TupleTableSlot * scanSlot = node -> ss .ss_ScanTupleSlot ;
613622
614- /* Fill scanSlot with a new tuple */
615- ExecStoreTuple (htup ,scanSlot ,InvalidBuffer , false);
616- }
623+ for (;;)
624+ {
625+ if (!node -> ss .ps .ps_TupFromTlist )
626+ {
627+ /* Fetch next tid pair if we're done with the SRF function */
628+ if (!fetch_next_pair (scan_state ))
629+ return NULL ;
617630}
618631
619632if (node -> ss .ps .ps_ProjInfo )