/** * Create a new index, populate existing data of the table and return its metadata. * @param txn the transaction in which the table is being created * @param index_name the name of the new index * @param table_name the name of the table * @param schema the schema of the table * @param key_schema the schema of the key * @param key_attrs key attributes * @param keysize size of the key * @return a pointer to the metadata of the new table */ template <classKeyType, classValueType, classKeyComparator> IndexInfo *CreateIndex(Transaction *txn, const std::string &index_name, const std::string &table_name, const Schema &schema, const Schema &key_schema, const std::vector<uint32_t> &key_attrs, keysize){ /* 1. 生成 index_oid 2. 生成 IndexInfo 结构 3. 保存 table name -> index names -> index id 的mapping关系 */ index_oid_t index_oid = next_index_oid_.fetch_add(1, std::memory_order_relaxed); IndexMetadata *idx_meta = newIndexMetadata(index_name, table_name, &schema, key_attrs); /* NOTE: Index 实例化到BPTree? */ // Index *idx = new Index(idx_meta); Index *idx = newBPlusTreeIndex<KeyType, ValueType, KeyComparator>(idx_meta, bpm_); IndexInfo *idx_info = newIndexInfo(key_schema, index_name, std::unique_ptr<Index>(idx), index_oid, table_name, keysize); /* generate mapping relation */ indexes_.insert(std::make_pair(index_oid, idx_info)); if (index_names_.count(table_name) == 0U) { index_names_.insert(std::make_pair(table_name, std::unordered_map<std::string, index_oid_t>())); } index_names_[table_name][index_name] = index_oid; /* populate all data */ // LOG_DEBUG("table name:%s, index name:%s", table_name.c_str(), index_name.c_str()); TableHeap *table = GetTable(table_name)->table_.get(); for (auto it = table->Begin(txn); it != table->End(); it++) { auto tmp = it->KeyFromTuple(schema, key_schema, key_attrs); // LOG_DEBUG("index key:%d", tmp.GetValue(&key_schema, 0).GetAs<uint32_t>()); idx->InsertEntry(it->KeyFromTuple(schema, key_schema, key_attrs), it->GetRid(), txn); } return idx_info; }
voidNestedLoopJoinExecutor::FetchAllTuples(){ std::vector<Tuple> left_tuples; std::vector<Tuple> right_tuples; { Tuple left_tuple; Tuple right_tuple; RID left_rid; RID right_rid; while (left_executor_->Next(&left_tuple, &left_rid)) { left_tuples.push_back(left_tuple); } while (right_executor_->Next(&right_tuple, &right_rid)) { right_tuples.push_back(right_tuple); } } /* now we have fetched all tuples in left and right table, it's time to combine them */ /* assume left table is smaller */ for (const Tuple &left : left_tuples) { for (const Tuple &right : right_tuples) { /* apply predicator */ if (plan_->Predicate() == nullptr || plan_->Predicate() ->EvaluateJoin(&left, left_executor_->GetOutputSchema(), &right, right_executor_->GetOutputSchema()) .GetAs<bool>()) { tmp_tuples_.push_back(GenerateFinalTuple(left, left_executor_->GetOutputSchema(), right, right_executor_->GetOutputSchema(), plan_->OutputSchema())); // save tuple into tmp_tuples_! } } } }
/** * @brief this implementation is a pipeline breaker, we generate all tuples * in left and right tables, and combine them together. Then use 2 for loop to * save them in "tmp_tuples_". For subsequent request, we only need to pop one * tuple from the "tmp_tuples_", and return it back */ boolNestedLoopJoinExecutor::Next(Tuple *tuple, RID *rid){ if (!tmp_tuples_.empty()) { *tuple = tmp_tuples_.back(); tmp_tuples_.pop_back(); returntrue; } /* no tuples or all tuples have been output */ returnfalse; }
/* fetch tuple from inner table by probe key, then combine inner tuple and outer tuple to form the final tuple */ for (size_t i = 0; i < index_probe_keys.size(); i++) { result_rids.clear(); idx->ScanKey(index_probe_keys[i], &result_rids, exec_ctx_->GetTransaction()); assert(result_rids.size() <= 1); if (result_rids.empty()) { /* not found */ continue; } if (!inner_table->GetTuple(result_rids[0], &inner_tuple, exec_ctx_->GetTransaction())) { LOG_ERROR("can't find the corresponding tuple in the inner table index"); abort(); /* or throw an exception */ } /* format inner tuple */ inner_tuple = ExtractTupleFromSchema(inner_tuple, &inner_table_meta_->schema_, plan_->InnerTableSchema()); /* predicate filter */ if (plan_->Predicate() == nullptr || plan_->Predicate() ->EvaluateJoin(&outter_tuples[i], plan_->OuterTableSchema(), &inner_tuple, plan_->InnerTableSchema()) .GetAs<bool>()) { tmp_tuples_.push_back(GenerateFinalTuple(outter_tuples[i], plan_->OuterTableSchema(), inner_tuple, plan_->InnerTableSchema(), plan_->OutputSchema())); } } }