@@ -101,7 +101,10 @@ static bool ExecParallelHashTuplePrealloc(HashJoinTable hashtable,
101
101
size_t size );
102
102
static void ExecParallelHashMergeCounters (HashJoinTable hashtable );
103
103
static void ExecParallelHashCloseBatchAccessors (HashJoinTable hashtable );
104
-
104
+ static void AddTupleValuesIntoRF (HashState * node , TupleTableSlot * slot );
105
+ static void PushdownRuntimeFilter (HashState * node );
106
+ static void FreeRuntimeFilter (HashState * node );
107
+ static void ResetRuntimeFilter (HashState * node );
105
108
106
109
/* ----------------------------------------------------------------
107
110
* ExecHash
@@ -192,7 +195,15 @@ MultiExecPrivateHash(HashState *node)
192
195
{
193
196
slot = ExecProcNode (outerNode );
194
197
if (TupIsNull (slot ))
198
+ {
199
+ if (gp_enable_runtime_filter_pushdown && node -> filters )
200
+ PushdownRuntimeFilter (node );
195
201
break ;
202
+ }
203
+
204
+ if (gp_enable_runtime_filter_pushdown && node -> filters )
205
+ AddTupleValuesIntoRF (node , slot );
206
+
196
207
/* We have to compute the hash value */
197
208
econtext -> ecxt_outertuple = slot ;
198
209
bool hashkeys_null = false;
@@ -334,6 +345,7 @@ MultiExecParallelHash(HashState *node)
334
345
slot = ExecProcNode (outerNode );
335
346
if (TupIsNull (slot ))
336
347
break ;
348
+
337
349
econtext -> ecxt_outertuple = slot ;
338
350
if (ExecHashGetHashValue (node , hashtable , econtext , hashkeys ,
339
351
false, hashtable -> keepNulls ,
@@ -511,6 +523,9 @@ ExecEndHash(HashState *node)
511
523
*/
512
524
outerPlan = outerPlanState (node );
513
525
ExecEndNode (outerPlan );
526
+
527
+ if (node -> filters )
528
+ FreeRuntimeFilter (node );
514
529
}
515
530
516
531
@@ -2519,6 +2534,9 @@ ExecReScanHash(HashState *node)
2519
2534
*/
2520
2535
if (node -> ps .lefttree -> chgParam == NULL )
2521
2536
ExecReScan (node -> ps .lefttree );
2537
+
2538
+ if (gp_enable_runtime_filter_pushdown && node -> filters )
2539
+ ResetRuntimeFilter (node );
2522
2540
}
2523
2541
2524
2542
@@ -4125,3 +4143,142 @@ get_hash_mem(void)
4125
4143
4126
4144
return (int ) mem_limit ;
4127
4145
}
4146
+
4147
+ /*
4148
+ * Convert AttrFilter to ScanKeyData and send these runtime filters to the
4149
+ * target node(seqscan).
4150
+ */
4151
+ void
4152
+ PushdownRuntimeFilter (HashState * node )
4153
+ {
4154
+ ListCell * lc ;
4155
+ List * scankeys ;
4156
+ ScanKey sk ;
4157
+ AttrFilter * attr_filter ;
4158
+
4159
+ foreach (lc , node -> filters )
4160
+ {
4161
+ scankeys = NIL ;
4162
+
4163
+ attr_filter = lfirst (lc );
4164
+ if (!IsA (attr_filter -> target , SeqScanState ) || attr_filter -> empty )
4165
+ continue ;
4166
+
4167
+ /* bloom filter */
4168
+ sk = (ScanKey )palloc0 (sizeof (ScanKeyData ));
4169
+ sk -> sk_flags = SK_BLOOM_FILTER ;
4170
+ sk -> sk_attno = attr_filter -> lattno ;
4171
+ sk -> sk_subtype = INT8OID ;
4172
+ sk -> sk_argument = PointerGetDatum (attr_filter -> blm_filter );
4173
+ scankeys = lappend (scankeys , sk );
4174
+
4175
+ /* range filter */
4176
+ sk = (ScanKey )palloc0 (sizeof (ScanKeyData ));
4177
+ sk -> sk_flags = 0 ;
4178
+ sk -> sk_attno = attr_filter -> lattno ;
4179
+ sk -> sk_strategy = BTGreaterEqualStrategyNumber ;
4180
+ sk -> sk_subtype = INT8OID ;
4181
+ sk -> sk_argument = attr_filter -> min ;
4182
+ scankeys = lappend (scankeys , sk );
4183
+
4184
+ sk = (ScanKey )palloc0 (sizeof (ScanKeyData ));
4185
+ sk -> sk_flags = 0 ;
4186
+ sk -> sk_attno = attr_filter -> lattno ;
4187
+ sk -> sk_strategy = BTLessEqualStrategyNumber ;
4188
+ sk -> sk_subtype = INT8OID ;
4189
+ sk -> sk_argument = attr_filter -> max ;
4190
+ scankeys = lappend (scankeys , sk );
4191
+
4192
+ /* append new runtime filters to target node */
4193
+ SeqScanState * sss = castNode (SeqScanState , attr_filter -> target );
4194
+ sss -> filters = list_concat (sss -> filters , scankeys );
4195
+ }
4196
+ }
4197
+
4198
+ static void
4199
+ AddTupleValuesIntoRF (HashState * node , TupleTableSlot * slot )
4200
+ {
4201
+ Datum val ;
4202
+ bool isnull ;
4203
+ ListCell * lc ;
4204
+ AttrFilter * attr_filter ;
4205
+
4206
+ foreach (lc , node -> filters )
4207
+ {
4208
+ attr_filter = (AttrFilter * ) lfirst (lc );
4209
+
4210
+ val = slot_getattr (slot , attr_filter -> rattno , & isnull );
4211
+ if (isnull )
4212
+ continue ;
4213
+
4214
+ attr_filter -> empty = false;
4215
+
4216
+ if ((int64_t )val < (int64_t )attr_filter -> min )
4217
+ attr_filter -> min = val ;
4218
+
4219
+ if ((int64_t )val > (int64_t )attr_filter -> max )
4220
+ attr_filter -> max = val ;
4221
+
4222
+ if (attr_filter -> blm_filter )
4223
+ bloom_add_element (attr_filter -> blm_filter , (unsigned char * )& val , sizeof (Datum ));
4224
+ }
4225
+ }
4226
+
4227
+ void
4228
+ FreeRuntimeFilter (HashState * node )
4229
+ {
4230
+ ListCell * lc ;
4231
+ AttrFilter * attr_filter ;
4232
+
4233
+ if (!node -> filters )
4234
+ return ;
4235
+
4236
+ foreach (lc , node -> filters )
4237
+ {
4238
+ attr_filter = lfirst (lc );
4239
+ if (attr_filter -> blm_filter )
4240
+ bloom_free (attr_filter -> blm_filter );
4241
+ }
4242
+
4243
+ list_free_deep (node -> filters );
4244
+ node -> filters = NIL ;
4245
+ }
4246
+
4247
+ void
4248
+ ResetRuntimeFilter (HashState * node )
4249
+ {
4250
+ ListCell * lc ;
4251
+ AttrFilter * attr_filter ;
4252
+ SeqScanState * sss ;
4253
+
4254
+ if (!node -> filters )
4255
+ return ;
4256
+
4257
+ foreach (lc , node -> filters )
4258
+ {
4259
+ attr_filter = lfirst (lc );
4260
+ attr_filter -> empty = true;
4261
+
4262
+ if (IsA (attr_filter -> target , SeqScanState ))
4263
+ {
4264
+ sss = castNode (SeqScanState , attr_filter -> target );
4265
+ if (sss -> filters )
4266
+ {
4267
+ list_free_deep (sss -> filters );
4268
+ sss -> filters = NIL ;
4269
+ }
4270
+ }
4271
+
4272
+ if (attr_filter -> blm_filter )
4273
+ bloom_free (attr_filter -> blm_filter );
4274
+
4275
+ attr_filter -> blm_filter = bloom_create_aggresive (node -> ps .plan -> plan_rows ,
4276
+ work_mem ,
4277
+ random ());
4278
+
4279
+ StaticAssertDecl (sizeof (LONG_MAX ) == sizeof (Datum ), "sizeof(LONG_MAX) should be equal to sizeof(Datum)" );
4280
+ StaticAssertDecl (sizeof (LONG_MIN ) == sizeof (Datum ), "sizeof(LONG_MIN) should be equal to sizeof(Datum)" );
4281
+ attr_filter -> min = LONG_MAX ;
4282
+ attr_filter -> max = LONG_MIN ;
4283
+ }
4284
+ }
0 commit comments