66//
77// Identification: src/common/bustub_ddl.cpp
88//
9- // Copyright (c) 2015-2025 , Carnegie Mellon University Database Group
9+ // Copyright (c) 2015-2026 , Carnegie Mellon University Database Group
1010//
1111// ===----------------------------------------------------------------------===//
1212
3737#include " common/util/string_util.h"
3838#include " concurrency/lock_manager.h"
3939#include " concurrency/transaction.h"
40+ #include " container/hash/hash_function.h"
4041#include " execution/execution_engine.h"
4142#include " execution/executor_context.h"
4243#include " execution/executors/mock_scan_executor.h"
5051#include " recovery/log_manager.h"
5152#include " storage/disk/disk_manager.h"
5253#include " storage/disk/disk_manager_memory.h"
54+ #include " storage/index/generic_key.h"
5355#include " type/value_factory.h"
5456
5557namespace bustub {
@@ -69,18 +71,39 @@ void BusTubInstance::HandleCreateStatement(Transaction *txn, const CreateStateme
6971 }
7072 auto key_schema = Schema::CopySchema (&info->schema_ , col_ids);
7173
72- // TODO(spring2023): If you want to support composite index key for leaderboard optimization, remove this assertion
73- // and create index with different key type that can hold multiple keys based on number of index columns.
74- //
75- // You can also create clustered index that directly stores value inside the index by modifying the value type.
76-
77- if (col_ids.empty () || col_ids.size () > 2 ) {
78- throw NotImplementedException (" only support creating index with exactly one or two columns" );
74+ if (col_ids.empty ()) {
75+ throw NotImplementedException (" Primary key cannot be empty" );
7976 }
8077
81- index = catalog_->CreateIndex <IntegerKeyType, IntegerValueType, IntegerComparatorType>(
82- txn, stmt.table_ + " _pk" , stmt.table_ , info->schema_ , key_schema, col_ids, TWO_INTEGER_SIZE,
83- IntegerHashFunctionType{}, true );
78+ // We compute the size (in bytes) of the index key
79+ uint32_t key_size = col_ids.size () * 4 ;
80+
81+ // We create an index of sufficient size depending on the key size.
82+ // ! NOTE: Currently, we support key sizes of at most 64 bytes.
83+ // ! This can be easily extended to support larger key sizes.
84+ if (key_size <= 4 ) {
85+ index = catalog_->CreateIndex <GenericKey<4 >, RID, GenericComparator<4 >>(txn, stmt.table_ + " _pk" , stmt.table_ ,
86+ info->schema_ , key_schema, col_ids, 4 ,
87+ HashFunction<GenericKey<4 >>{}, true );
88+ } else if (key_size <= 8 ) {
89+ index = catalog_->CreateIndex <GenericKey<8 >, RID, GenericComparator<8 >>(txn, stmt.table_ + " _pk" , stmt.table_ ,
90+ info->schema_ , key_schema, col_ids, 8 ,
91+ HashFunction<GenericKey<8 >>{}, true );
92+ } else if (key_size <= 16 ) {
93+ index = catalog_->CreateIndex <GenericKey<16 >, RID, GenericComparator<16 >>(txn, stmt.table_ + " _pk" , stmt.table_ ,
94+ info->schema_ , key_schema, col_ids, 16 ,
95+ HashFunction<GenericKey<16 >>{}, true );
96+ } else if (key_size <= 32 ) {
97+ index = catalog_->CreateIndex <GenericKey<32 >, RID, GenericComparator<32 >>(txn, stmt.table_ + " _pk" , stmt.table_ ,
98+ info->schema_ , key_schema, col_ids, 32 ,
99+ HashFunction<GenericKey<32 >>{}, true );
100+ } else if (key_size <= 64 ) {
101+ index = catalog_->CreateIndex <GenericKey<64 >, RID, GenericComparator<64 >>(txn, stmt.table_ + " _pk" , stmt.table_ ,
102+ info->schema_ , key_schema, col_ids, 64 ,
103+ HashFunction<GenericKey<64 >>{}, true );
104+ } else {
105+ throw NotImplementedException (" Unsupported: primary key size exceeds 64 bytes" );
106+ }
84107 }
85108 l.unlock ();
86109
@@ -108,41 +131,56 @@ void BusTubInstance::HandleIndexStatement(Transaction *txn, const IndexStatement
108131 }
109132 auto key_schema = Schema::CopySchema (&stmt.table_ ->schema_ , col_ids);
110133
111- // TODO(spring2023): If you want to support composite index key for leaderboard optimization, remove this assertion
112- // and create index with different key type that can hold multiple keys based on number of index columns.
113- //
114- // You can also create clustered index that directly stores value inside the index by modifying the value type.
115-
116- if (col_ids.empty () || col_ids.size () > 2 ) {
117- throw NotImplementedException (" only support creating index with exactly one or two columns" );
134+ if (col_ids.empty ()) {
135+ throw NotImplementedException (" Index columns cannot be empty" );
118136 }
119137
120138 std::unique_lock<std::shared_mutex> l (catalog_lock_);
121139 std::shared_ptr<IndexInfo> info = nullptr ;
122140
123- if (stmt.index_type_ .empty ()) {
124- info = catalog_->CreateIndex <IntegerKeyType, IntegerValueType, IntegerComparatorType>(
125- txn, stmt.index_name_ , stmt.table_ ->table_ , stmt.table_ ->schema_ , key_schema, col_ids, TWO_INTEGER_SIZE,
126- IntegerHashFunctionType{}, false ); // create default index
127- } else if (stmt.index_type_ == " hash" ) {
128- info = catalog_->CreateIndex <IntegerKeyType, IntegerValueType, IntegerComparatorType>(
129- txn, stmt.index_name_ , stmt.table_ ->table_ , stmt.table_ ->schema_ , key_schema, col_ids, TWO_INTEGER_SIZE,
130- IntegerHashFunctionType{}, false , IndexType::HashTableIndex);
131- } else if (stmt.index_type_ == " bplustree" ) {
132- info = catalog_->CreateIndex <IntegerKeyType, IntegerValueType, IntegerComparatorType>(
133- txn, stmt.index_name_ , stmt.table_ ->table_ , stmt.table_ ->schema_ , key_schema, col_ids, TWO_INTEGER_SIZE,
134- IntegerHashFunctionType{}, false , IndexType::BPlusTreeIndex);
141+ IndexType index_type = IndexType::BPlusTreeIndex; // Default
142+ if (stmt.index_type_ == " hash" ) {
143+ index_type = IndexType::HashTableIndex;
144+ } else if (stmt.index_type_ == " bplustree" || stmt.index_type_ .empty ()) {
145+ index_type = IndexType::BPlusTreeIndex;
135146 } else if (stmt.index_type_ == " stl_ordered" ) {
136- info = catalog_->CreateIndex <IntegerKeyType, IntegerValueType, IntegerComparatorType>(
137- txn, stmt.index_name_ , stmt.table_ ->table_ , stmt.table_ ->schema_ , key_schema, col_ids, TWO_INTEGER_SIZE,
138- IntegerHashFunctionType{}, false , IndexType::STLOrderedIndex);
147+ index_type = IndexType::STLOrderedIndex;
139148 } else if (stmt.index_type_ == " stl_unordered" ) {
140- info = catalog_->CreateIndex <IntegerKeyType, IntegerValueType, IntegerComparatorType>(
141- txn, stmt.index_name_ , stmt.table_ ->table_ , stmt.table_ ->schema_ , key_schema, col_ids, TWO_INTEGER_SIZE,
142- IntegerHashFunctionType{}, false , IndexType::STLUnorderedIndex);
149+ index_type = IndexType::STLUnorderedIndex;
143150 } else {
144151 UNIMPLEMENTED (" unsupported index type " + stmt.index_type_ );
145152 }
153+
154+ // We compute the size (in bytes) of the index key
155+ uint32_t key_size = col_ids.size () * 4 ;
156+
157+ // We create an index of sufficient size depending on the key size.
158+ // ! NOTE: Currently, we support key sizes of at most 64 bytes.
159+ // ! This can be easily extended to support larger key sizes.
160+ if (key_size <= 4 ) {
161+ info = catalog_->CreateIndex <GenericKey<4 >, RID, GenericComparator<4 >>(
162+ txn, stmt.index_name_ , stmt.table_ ->table_ , stmt.table_ ->schema_ , key_schema, col_ids, 4 ,
163+ HashFunction<GenericKey<4 >>{}, false , index_type);
164+ } else if (key_size <= 8 ) {
165+ info = catalog_->CreateIndex <GenericKey<8 >, RID, GenericComparator<8 >>(
166+ txn, stmt.index_name_ , stmt.table_ ->table_ , stmt.table_ ->schema_ , key_schema, col_ids, 8 ,
167+ HashFunction<GenericKey<8 >>{}, false , index_type);
168+ } else if (key_size <= 16 ) {
169+ info = catalog_->CreateIndex <GenericKey<16 >, RID, GenericComparator<16 >>(
170+ txn, stmt.index_name_ , stmt.table_ ->table_ , stmt.table_ ->schema_ , key_schema, col_ids, 16 ,
171+ HashFunction<GenericKey<16 >>{}, false , index_type);
172+ } else if (key_size <= 32 ) {
173+ info = catalog_->CreateIndex <GenericKey<32 >, RID, GenericComparator<32 >>(
174+ txn, stmt.index_name_ , stmt.table_ ->table_ , stmt.table_ ->schema_ , key_schema, col_ids, 32 ,
175+ HashFunction<GenericKey<32 >>{}, false , index_type);
176+ } else if (key_size <= 64 ) {
177+ info = catalog_->CreateIndex <GenericKey<64 >, RID, GenericComparator<64 >>(
178+ txn, stmt.index_name_ , stmt.table_ ->table_ , stmt.table_ ->schema_ , key_schema, col_ids, 64 ,
179+ HashFunction<GenericKey<64 >>{}, false , index_type);
180+ } else {
181+ throw NotImplementedException (" Unsupported: index key size exceeds 64 bytes" );
182+ }
183+
146184 l.unlock ();
147185
148186 if (info == nullptr ) {
0 commit comments