@@ -33,26 +33,70 @@ void FilterExecutor::Init() {
3333}
3434
3535/* *
36- * Yield the next tuple from the filter.
37- * @param[out] tuple The next tuple produced by the filter
38- * @param[out] rid The next tuple RID produced by the filter
36+ * Yield the next tuple batch from the filter.
37+ * @param[out] tuple_batch The next tuple batch produced by the filter
38+ * @param[out] rid_batch The next tuple RID batch produced by the filter
39+ * @param batch_size The number of tuples to be included in the batch (default: BUSTUB_BATCH_SIZE)
3940 * @return `true` if a tuple was produced, `false` if there are no more tuples
4041 */
41- auto FilterExecutor::Next (Tuple *tuple, RID *rid) -> bool {
42+ auto FilterExecutor::Next (std::vector<bustub::Tuple> *tuple_batch, std::vector<bustub::RID> *rid_batch,
43+ size_t batch_size) -> bool {
44+ tuple_batch->clear ();
45+ rid_batch->clear ();
46+
4247 auto filter_expr = plan_->GetPredicate ();
4348
4449 while (true ) {
45- // Get the next tuple
46- const auto status = child_executor_->Next (tuple, rid);
50+ // If the child offset is not zero, process remaining tuples in the last fetched batch
51+ if (child_offset_ != 0 ) {
52+ for (size_t i = child_offset_; i < child_tuples_.size (); ++i) {
53+ auto &tuple = child_tuples_[i];
54+ auto &rid = child_rids_[i];
55+ // Evaluate the filter predicate
56+ auto value = filter_expr->Evaluate (&tuple, child_executor_->GetOutputSchema ());
57+ if (filter_expr == nullptr || (!value.IsNull () && value.GetAs <bool >())) {
58+ tuple_batch->push_back (tuple);
59+ rid_batch->push_back (rid);
60+ }
61+ }
62+ }
63+
64+ child_offset_ = 0 ;
65+
66+ // Get the next tuple batch from the child executor
67+ const auto status = child_executor_->Next (&child_tuples_, &child_rids_, batch_size);
4768
48- if (!status) {
69+ // If no more tuples and output batch is empty, return false
70+ if (!status && tuple_batch->empty ()) {
4971 return false ;
5072 }
5173
52- auto value = filter_expr-> Evaluate (tuple, child_executor_-> GetOutputSchema ());
53- if (!value. IsNull () && value. GetAs < bool > ()) {
74+ // If no more tuples but output batch is not empty, return true
75+ if (!status && !tuple_batch-> empty ()) {
5476 return true ;
5577 }
78+
79+ for (size_t i = 0 ; i < child_tuples_.size (); ++i) {
80+ auto &tuple = child_tuples_[i];
81+ auto &rid = child_rids_[i];
82+ // Evaluate the filter predicate
83+ auto value = filter_expr->Evaluate (&tuple, child_executor_->GetOutputSchema ());
84+ if (filter_expr == nullptr || (!value.IsNull () && value.GetAs <bool >())) {
85+ tuple_batch->push_back (tuple);
86+ rid_batch->push_back (rid);
87+ if (tuple_batch->size () >= batch_size) {
88+ // If we have filled the output batch but not yet reached the end of the current child batch, update the
89+ // offset and return
90+ if (i + 1 < child_tuples_.size ()) {
91+ child_offset_ = i + 1 ;
92+ } else {
93+ child_offset_ = 0 ;
94+ }
95+
96+ return true ;
97+ }
98+ }
99+ }
56100 }
57101}
58102
0 commit comments