QuillSQL
✨ Highlights
- Clean architecture: SQL → Logical Plan → Physical Plan → Volcano executor
- Transaction control:
BEGIN/COMMIT/ROLLBACK
,SET TRANSACTION
,SET SESSION TRANSACTION
, enforcedREAD ONLY
, row/table locks - B+Tree index: OLC readers, B-link pages, latch crabbing, range scan iterator
- Buffer pool: LRU-K, pin/unpin with RAII guards, flush-on-evict
- Streaming scan: Large sequential scans bypass buffer pool via a small direct I/O ring buffer to avoid cache pollution
- WAL & Recovery (ARIES-inspired): FPW + PageDelta, DPT, chained CLR, per-transaction undo chains, idempotent replays
- Information schema:
information_schema.schemas
,tables
,columns
,indexes
- Now supports:
SHOW DATABASES
,SHOW TABLES
,EXPLAIN
,DELETE
- Docs: Architecture · Buffer Pool · B+ Tree Index · Disk I/O · WAL & Recovery · Transactions
🎓 Teaching & Research Friendly
- Clear module boundaries, suitable for classroom assignments and research prototypes. Inspired by CMU 15-445 BusTub with strengthened WAL/Recovery, observability, and centralized configuration.
- Pluggable pieces: buffer pool, index, WAL, and recovery are decoupled for side-by-side experiments.
- Readability-first: simple, pragmatic code with minimal hot-path allocations.
🚀 Quick Start
# or open a persistent DB file
# start web server (http://127.0.0.1:8080)
# specify data file and listening addr
QUILL_DB_FILE=my.db QUILL_HTTP_ADDR=0.0.0.0:8080
# batch API (optional)
Sample session:
INT, v INT DEFAULT 0);
INSERT INTO t(id, v) VALUES (1, 10), (2, 20), (3, 30);
SELECT id, v FROM t WHERE v > 10 ORDER BY id DESC LIMIT 1;
SHOW DATABASES;
SHOW TABLES;
EXPLAIN SELECT id, COUNT(*) FROM t GROUP BY id ORDER BY id;
(id
🧱 Supported SQL
-
Data types
BOOLEAN
,INT8/16/32/64
,UINT8/16/32/64
,FLOAT32/64
,VARCHAR(n)
-
CREATE TABLE
- Column options:
NOT NULL
|DEFAULT <literal>
- Example:
NOT NULL, v INT32 DEFAULT 0 ); ( id INT64
- Column options:
-
CREATE INDEX
- Example:
(id);
- Example:
-
INSERT
INSERT INTO ... VALUES (...)
andINSERT INTO ... SELECT ...
-
SELECT
-
Projection: columns, literals, aliases
-
FROM: table | subquery (
FROM (SELECT ...)
) — alias not yet supported -
WHERE: comparison/logical operators
= != > >= < <= AND OR
-
GROUP BY: aggregates
COUNT(expr|*)
,AVG(expr)
-
ORDER BY:
ASC|DESC
, supportsNULLS FIRST|LAST
-
LIMIT/OFFSET
-
JOIN:
INNER JOIN
(withON
condition),CROSS JOIN
-
UPDATE
UPDATE t SET col = expr [, ...] [WHERE predicate]
-
DELETE
DELETE FROM t [WHERE predicate]
-
SHOW
-
SHOW DATABASES;
(rewritten toSELECT schema FROM information_schema.schemas
) -
SHOW TABLES;
(rewritten toSELECT table_name FROM information_schema.tables
) -
EXPLAIN
EXPLAIN <statement>
returns a single column namedplan
with multiple lines showing the logical plan tree
⚠️ Current Limitations
- Not yet supported:
DROP
,ALTER
, MVCC, predicate locking. - Not implemented: outer joins (Left/Right/Full), arithmetic expressions, table/subquery aliases
ORDER BY
DESC
/NULLS FIRST|LAST
currently affects sorting only (not storage layout)
🧪 Testing
⚙️ Configuration
Programmatic configs (centralized)
- Build
DatabaseOptions { wal: WalOptions { .. } }
and pass it toDatabase::new_*_with_options(..)
; WAL/scan are centrally managed bycrate::config
. - Key structs:
IOStrategy
,IOSchedulerConfig
,BufferPoolConfig
,BTreeConfig
,TableScanConfig
,WalConfig
/WalOptions
.
Minimal environment variables (runtime only)
- PORT: bind port (overrides the port of
QUILL_HTTP_ADDR
) - QUILL_HTTP_ADDR: listen address (default
0.0.0.0:8080
) - QUILL_DB_FILE: path to database file (uses a temp DB if unset)
- QUILL_DEFAULT_ISOLATION: default session isolation (
read-uncommitted
,read-committed
,repeatable-read
,serializable
) - RUST_LOG: log level (e.g., info, debug)
Example (Rust)
use Arc;
use ;
use DiskManager;
use DiskScheduler;
use BufferPoolManager;
// Disk I/O backend: ThreadPool or Linux io_uring
let dm = new;
let scheduler = new;
// Buffer pool
let bpm = new;
// B+Tree iterator tuning (batch window & prefetch)
let btree_cfg = BTreeConfig ;
// Table scan tuning (streaming readahead)
let table_scan_cfg = TableScanConfig ;
// WAL config (centralized)
use WalConfig;
let wal_cfg = WalConfig ;
Notes
- io_uring is Linux-only; non-Linux will fall back to the thread pool.
- Streaming/RingBuffer optimizations are controlled via
BTreeConfig
/TableScanConfig
instead of env vars.
📦 Docker
# build
# run (ephemeral in-memory DB)
# run with persistent file mounted
Includes sqllogictest-based cases:
src/tests/sql_example/create_table.slt
src/tests/sql_example/create_index.slt
src/tests/sql_example/insert.slt
src/tests/sql_example/show_explain.slt
src/tests/sql_example/delete.slt