This project is a simple, from-scratch database implementation in C. It uses a B-Tree to store data, persists records to a file, and provides a basic SQL-like command-line interface (REPL). The primary purpose of this project is educational, demonstrating core database concepts like data structures, file I/O, serialization, and command parsing.
- CRUD Operations:
insert
,select
(all or by ID), anddrop
(by ID). - B-Tree for Indexing: Data is stored and indexed in a B-Tree, allowing for efficient range queries and lookups. The primary key is an integer
id
. - File-Based Persistence: The database is saved to a single file, which can be reloaded in subsequent sessions.
- File-Based Import/Export: The database can be imported or exported using a csv file.
- In-Memory Page Cache: A pager manages reading and writing fixed-size pages from the file into memory to reduce I/O overhead.
- Interactive REPL: A simple Read-Eval-Print Loop for interacting with the database.
- Meta-Commands: Special commands for inspecting the database state (e.g., printing the B-Tree structure).
You need a C compiler (MinGW
to use getline() function). It is implemented to work in UNIX Environments like linux, MacOS or WSL.
make
make run
-
insert {id} {username} {email}
Inserts a new user record.id
: non-negative integerusername
: max 32 charactersemail
: max 255 characters
Example:
insert 1 alice alice@example.com
-
select
Retrieves and prints all records, sorted byid
.
Example:select
-
select {id}
Retrieves a single record with the givenid
.
Example:select 1
-
drop {id}
Deletes the record with the givenid
.
Example:drop 1
-
import '{file.csv}'
Imports content of csv file with namefile.csv
. Example:import 'example.csv'
-
export '{file.csv}'
Exports records to csv file with namefile.csv
. Example:export 'records.csv'
-
.exit
Flushes changes and exits the program. -
.btree
Displays the B-Tree structure. -
.constants
Shows database constants (node size, page capacity, etc.) -
.commands
Prints a list of available commands.
- Database file is divided into 4096-byte pages.
- A
DbPager
handles:- Reading pages from disk to memory.
- Writing modified pages back to disk.
- Reduces disk I/O through in-memory caching.
- Supports efficient lookups, insertions, and ordered scans.
- Node Types:
- LEAF: Holds (key, value) pairs. Value is serialized
UserRow
. - INTERNAL: Guides traversal with keys and child pointers.
- LEAF: Holds (key, value) pairs. Value is serialized
-
Insertion:
- Find correct leaf node.
- Insert key; split node if full.
- Splits may propagate up, creating a new root.
-
Search:
- Starts at root.
- Traverses internal nodes based on key comparisons.
- The main loop:
- Reads input.
- Parses into a
Statement
(prepare_statement
). - Executes using
execute_statement
. - Interacts with the B-Tree using
TableCursor
.
TableCursor
points to specific row in the table.- Simplifies traversal of the B-Tree.
- Supports row access and iteration.
- ❌ No Transactions – risk of corruption on crash during B-Tree operations
- ❌ No Concurrency – not safe for multi-threaded or multi-process access
- ❌ Fixed Schema – only supports
{id, username, email}
- ❌ Limited Query Language – no
WHERE
,JOIN
, or aggregation - ❌ No Secondary Indexes – queries on non-primary keys are inefficient
This project is licensed under the MIT License.