56
56
* are prepared to return the first tuple.
57
57
* ----------------------------------------------------------------
58
58
*/
59
+
60
+ static inline TupleTableSlot * * fetchNextBlock (PlanState * plan ) {
61
+ /* NEVER set outerTupleSlots[BLOCK_SIZE] to value other than NULL, it's the terimiator of the loop! */
62
+ static TupleTableSlot * blockData [BLOCK_SIZE + 1 ] = { NULL };
63
+ for (unsigned long idx = 0 ; idx < BLOCK_SIZE ; ++ idx ) {
64
+ blockData [idx ] = ExecProcNode (plan );
65
+ if (TupIsNull (blockData [idx ])) {
66
+ if (idx == 0 ) {
67
+ ENL1_printf ("no outer tuple, ending join" );
68
+ return NULL ;
69
+ } else {
70
+ return blockData ;
71
+ }
72
+ }
73
+ }
74
+ return blockData ;
75
+ }
76
+
59
77
TupleTableSlot *
60
78
ExecNestLoop (NestLoopState * node )
61
79
{
@@ -119,8 +137,15 @@ ExecNestLoop(NestLoopState *node)
119
137
*/
120
138
if (node -> nl_NeedNewOuter )
121
139
{
122
- ENL1_printf ("getting new outer tuple" );
123
- outerTupleSlot = ExecProcNode (outerPlan );
140
+ ENL1_printf ("getting new outer tuples" );
141
+ outerTupleSlot = * (++ econtext -> ecxt_outertuples );
142
+ if (TupIsNull (outerTupleSlot )) {
143
+ if ((econtext -> ecxt_outertuples = fetchNextBlock (outerPlan )) == NULL ) {
144
+ ENL1_printf ("no outer tuple, ending join" );
145
+ return NULL ;
146
+ }
147
+ outerTupleSlot = * econtext -> ecxt_outertuples ;
148
+ }
124
149
125
150
/*
126
151
* if there are no more outer tuples, then the join is complete..
@@ -132,7 +157,6 @@ ExecNestLoop(NestLoopState *node)
132
157
}
133
158
134
159
ENL1_printf ("saving new outer tuple information" );
135
- econtext -> ecxt_outertuple = outerTupleSlot ;
136
160
node -> nl_NeedNewOuter = false;
137
161
node -> nl_MatchedOuter = false;
138
162
@@ -439,3 +463,5 @@ ExecReScanNestLoop(NestLoopState *node)
439
463
node -> nl_NeedNewOuter = true;
440
464
node -> nl_MatchedOuter = false;
441
465
}
466
+
467
+
0 commit comments