4848#include "utils/rel.h"
4949#include "utils/spccache.h"
5050
51+ static void BitmapTableScanSetup (BitmapHeapScanState * node );
5152static TupleTableSlot * BitmapHeapNext (BitmapHeapScanState * node );
5253static inline void BitmapDoneInitializingSharedState (ParallelBitmapHeapState * pstate );
5354static inline void BitmapAdjustPrefetchIterator (BitmapHeapScanState * node );
@@ -57,6 +58,107 @@ static inline void BitmapPrefetch(BitmapHeapScanState *node,
5758static bool BitmapShouldInitializeSharedState (ParallelBitmapHeapState * pstate );
5859
5960
61+ /*
62+ * Do the underlying index scan, build the bitmap, set up the parallel state
63+ * needed for parallel workers to iterate through the bitmap, and set up the
64+ * underlying table scan descriptor.
65+ *
66+ * For prefetching, we use *two* iterators, one for the pages we are actually
67+ * scanning and another that runs ahead of the first for prefetching.
68+ * node->prefetch_pages tracks exactly how many pages ahead the prefetch
69+ * iterator is. Also, node->prefetch_target tracks the desired prefetch
70+ * distance, which starts small and increases up to the
71+ * node->prefetch_maximum. This is to avoid doing a lot of prefetching in a
72+ * scan that stops after a few tuples because of a LIMIT.
73+ */
74+ static void
75+ BitmapTableScanSetup (BitmapHeapScanState * node )
76+ {
77+ TBMIterator tbmiterator = {0 };
78+ ParallelBitmapHeapState * pstate = node -> pstate ;
79+ dsa_area * dsa = node -> ss .ps .state -> es_query_dsa ;
80+
81+ if (!pstate )
82+ {
83+ node -> tbm = (TIDBitmap * ) MultiExecProcNode (outerPlanState (node ));
84+
85+ if (!node -> tbm || !IsA (node -> tbm , TIDBitmap ))
86+ elog (ERROR , "unrecognized result from subplan" );
87+ }
88+ else if (BitmapShouldInitializeSharedState (pstate ))
89+ {
90+ /*
91+ * The leader will immediately come out of the function, but others
92+ * will be blocked until leader populates the TBM and wakes them up.
93+ */
94+ node -> tbm = (TIDBitmap * ) MultiExecProcNode (outerPlanState (node ));
95+ if (!node -> tbm || !IsA (node -> tbm , TIDBitmap ))
96+ elog (ERROR , "unrecognized result from subplan" );
97+
98+ /*
99+ * Prepare to iterate over the TBM. This will return the dsa_pointer
100+ * of the iterator state which will be used by multiple processes to
101+ * iterate jointly.
102+ */
103+ pstate -> tbmiterator = tbm_prepare_shared_iterate (node -> tbm );
104+
105+ #ifdef USE_PREFETCH
106+ if (node -> prefetch_maximum > 0 )
107+ {
108+ pstate -> prefetch_iterator =
109+ tbm_prepare_shared_iterate (node -> tbm );
110+ }
111+ #endif /* USE_PREFETCH */
112+
113+ /* We have initialized the shared state so wake up others. */
114+ BitmapDoneInitializingSharedState (pstate );
115+ }
116+
117+ tbmiterator = tbm_begin_iterate (node -> tbm , dsa ,
118+ pstate ?
119+ pstate -> tbmiterator :
120+ InvalidDsaPointer );
121+
122+ #ifdef USE_PREFETCH
123+ if (node -> prefetch_maximum > 0 )
124+ node -> prefetch_iterator =
125+ tbm_begin_iterate (node -> tbm , dsa ,
126+ pstate ?
127+ pstate -> prefetch_iterator :
128+ InvalidDsaPointer );
129+ #endif /* USE_PREFETCH */
130+
131+ /*
132+ * If this is the first scan of the underlying table, create the table
133+ * scan descriptor and begin the scan.
134+ */
135+ if (!node -> ss .ss_currentScanDesc )
136+ {
137+ bool need_tuples = false;
138+
139+ /*
140+ * We can potentially skip fetching heap pages if we do not need any
141+ * columns of the table, either for checking non-indexable quals or
142+ * for returning data. This test is a bit simplistic, as it checks
143+ * the stronger condition that there's no qual or return tlist at all.
144+ * But in most cases it's probably not worth working harder than that.
145+ */
146+ need_tuples = (node -> ss .ps .plan -> qual != NIL ||
147+ node -> ss .ps .plan -> targetlist != NIL );
148+
149+ node -> ss .ss_currentScanDesc =
150+ table_beginscan_bm (node -> ss .ss_currentRelation ,
151+ node -> ss .ps .state -> es_snapshot ,
152+ 0 ,
153+ NULL ,
154+ need_tuples );
155+ }
156+
157+ node -> ss .ss_currentScanDesc -> st .rs_tbmiterator = tbmiterator ;
158+ node -> initialized = true;
159+ }
160+
161+
60162/* ----------------------------------------------------------------
61163 * BitmapHeapNext
62164 *
@@ -68,121 +170,27 @@ BitmapHeapNext(BitmapHeapScanState *node)
68170{
69171 ExprContext * econtext ;
70172 TableScanDesc scan ;
71- TIDBitmap * tbm ;
72173 TupleTableSlot * slot ;
174+
175+ #ifdef USE_PREFETCH
73176 ParallelBitmapHeapState * pstate = node -> pstate ;
74- dsa_area * dsa = node -> ss . ps . state -> es_query_dsa ;
177+ #endif
75178
76179 /*
77180 * extract necessary information from index scan node
78181 */
79182 econtext = node -> ss .ps .ps_ExprContext ;
80183 slot = node -> ss .ss_ScanTupleSlot ;
81184 scan = node -> ss .ss_currentScanDesc ;
82- tbm = node -> tbm ;
83185
84186 /*
85187 * If we haven't yet performed the underlying index scan, do it, and begin
86188 * the iteration over the bitmap.
87- *
88- * For prefetching, we use *two* iterators, one for the pages we are
89- * actually scanning and another that runs ahead of the first for
90- * prefetching. node->prefetch_pages tracks exactly how many pages ahead
91- * the prefetch iterator is. Also, node->prefetch_target tracks the
92- * desired prefetch distance, which starts small and increases up to the
93- * node->prefetch_maximum. This is to avoid doing a lot of prefetching in
94- * a scan that stops after a few tuples because of a LIMIT.
95189 */
96190 if (!node -> initialized )
97191 {
98- TBMIterator tbmiterator ;
99-
100- if (!pstate )
101- {
102- tbm = (TIDBitmap * ) MultiExecProcNode (outerPlanState (node ));
103-
104- if (!tbm || !IsA (tbm , TIDBitmap ))
105- elog (ERROR , "unrecognized result from subplan" );
106-
107- node -> tbm = tbm ;
108- }
109- else if (BitmapShouldInitializeSharedState (pstate ))
110- {
111- /*
112- * The leader will immediately come out of the function, but
113- * others will be blocked until leader populates the TBM and wakes
114- * them up.
115- */
116- tbm = (TIDBitmap * ) MultiExecProcNode (outerPlanState (node ));
117- if (!tbm || !IsA (tbm , TIDBitmap ))
118- elog (ERROR , "unrecognized result from subplan" );
119-
120- node -> tbm = tbm ;
121-
122- /*
123- * Prepare to iterate over the TBM. This will return the
124- * dsa_pointer of the iterator state which will be used by
125- * multiple processes to iterate jointly.
126- */
127- pstate -> tbmiterator = tbm_prepare_shared_iterate (tbm );
128-
129- #ifdef USE_PREFETCH
130- if (node -> prefetch_maximum > 0 )
131- {
132- pstate -> prefetch_iterator =
133- tbm_prepare_shared_iterate (tbm );
134- }
135- #endif /* USE_PREFETCH */
136-
137- /* We have initialized the shared state so wake up others. */
138- BitmapDoneInitializingSharedState (pstate );
139- }
140-
141- tbmiterator = tbm_begin_iterate (tbm , dsa ,
142- pstate ?
143- pstate -> tbmiterator :
144- InvalidDsaPointer );
145-
146- #ifdef USE_PREFETCH
147- if (node -> prefetch_maximum > 0 )
148- node -> prefetch_iterator =
149- tbm_begin_iterate (tbm , dsa ,
150- pstate ?
151- pstate -> prefetch_iterator :
152- InvalidDsaPointer );
153- #endif /* USE_PREFETCH */
154-
155- /*
156- * If this is the first scan of the underlying table, create the table
157- * scan descriptor and begin the scan.
158- */
159- if (!scan )
160- {
161- bool need_tuples = false;
162-
163- /*
164- * We can potentially skip fetching heap pages if we do not need
165- * any columns of the table, either for checking non-indexable
166- * quals or for returning data. This test is a bit simplistic, as
167- * it checks the stronger condition that there's no qual or return
168- * tlist at all. But in most cases it's probably not worth working
169- * harder than that.
170- */
171- need_tuples = (node -> ss .ps .plan -> qual != NIL ||
172- node -> ss .ps .plan -> targetlist != NIL );
173-
174- scan = table_beginscan_bm (node -> ss .ss_currentRelation ,
175- node -> ss .ps .state -> es_snapshot ,
176- 0 ,
177- NULL ,
178- need_tuples );
179-
180- node -> ss .ss_currentScanDesc = scan ;
181- }
182-
183- scan -> st .rs_tbmiterator = tbmiterator ;
184- node -> initialized = true;
185-
192+ BitmapTableScanSetup (node );
193+ scan = node -> ss .ss_currentScanDesc ;
186194 goto new_page ;
187195 }
188196
0 commit comments