48
48
#include "utils/rel.h"
49
49
#include "utils/spccache.h"
50
50
51
+ static void BitmapTableScanSetup (BitmapHeapScanState * node );
51
52
static TupleTableSlot * BitmapHeapNext (BitmapHeapScanState * node );
52
53
static inline void BitmapDoneInitializingSharedState (ParallelBitmapHeapState * pstate );
53
54
static inline void BitmapAdjustPrefetchIterator (BitmapHeapScanState * node );
@@ -57,6 +58,107 @@ static inline void BitmapPrefetch(BitmapHeapScanState *node,
57
58
static bool BitmapShouldInitializeSharedState (ParallelBitmapHeapState * pstate );
58
59
59
60
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
+
60
162
/* ----------------------------------------------------------------
61
163
* BitmapHeapNext
62
164
*
@@ -68,121 +170,27 @@ BitmapHeapNext(BitmapHeapScanState *node)
68
170
{
69
171
ExprContext * econtext ;
70
172
TableScanDesc scan ;
71
- TIDBitmap * tbm ;
72
173
TupleTableSlot * slot ;
174
+
175
+ #ifdef USE_PREFETCH
73
176
ParallelBitmapHeapState * pstate = node -> pstate ;
74
- dsa_area * dsa = node -> ss . ps . state -> es_query_dsa ;
177
+ #endif
75
178
76
179
/*
77
180
* extract necessary information from index scan node
78
181
*/
79
182
econtext = node -> ss .ps .ps_ExprContext ;
80
183
slot = node -> ss .ss_ScanTupleSlot ;
81
184
scan = node -> ss .ss_currentScanDesc ;
82
- tbm = node -> tbm ;
83
185
84
186
/*
85
187
* If we haven't yet performed the underlying index scan, do it, and begin
86
188
* 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.
95
189
*/
96
190
if (!node -> initialized )
97
191
{
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 ;
186
194
goto new_page ;
187
195
}
188
196
0 commit comments