The Tree Module: Where Pages Turn Into Rows in SQLite
Source: Dev.to
Hello, I’m Maneshwar. I’m working on FreeDevTools online — building “one place for all dev tools, cheat codes, and TLDRs,” a free, open‑source hub where developers can quickly find and use tools without the hassle of searching all over the internet.
From Pager to Tree
In the previous chapter we stopped at the pager.
The pager gave SQLite something extremely important—but also very limited: a page‑oriented view of a byte stream.
You could ask for page 17, modify it, pin it, unpin it—but the pager had no idea what a row, column, or record was.
That gap is exactly where the tree module steps in.
The tree module takes this flat, page‑oriented world and turns it into something the VM can reason about: a tuple‑oriented, key‑sequenced file.
From this point onward, the VM no longer thinks in terms of pages. It thinks in terms of tuples—ordered, searchable, insertable units of data.
What Exactly Is a Tuple in SQLite?
Before going any further, it’s worth slowing down and clearing up a very common confusion.
- A tuple in SQLite is not a datatype.
- It’s also not a C struct, not a row object, and not something the tree module tries to interpret semantically.
A tuple is simply:
- A logical row of a relation as seen by the VM, represented internally as a variable‑length byte sequence.
- Treated as opaque data by the tree module.
In other words, the tree module does not care whether a tuple represents:
- A table row with columns, or
- An index entry with key + rowid.
Metadata from sqlite_master is stored separately. To the tree module, all of these are just byte strings with an associated key. Meaning is imposed above the tree module, primarily by the VM and the record‑format logic.
Why Tuples Need Organization at All
A relation is conceptually a set of tuples, but sets alone are not enough for efficient access. The VM needs guarantees:
- Find tuples by key
- Scan tuples in order
- Insert and delete tuples efficiently
- Keep tuples of different relations separate, even though they live in the same file
Classic ways to organize tuples include:
- Entry sequence (append‑only)
- Relative positioning
- Hash‑based organization
- Key‑sequenced organization (SQLite’s choice)
Each choice affects how inserts, lookups, and deletes behave.
SQLite’s One‑Big Design Decision: Everything Is a Tree
SQLite uses exactly one organization technique for persistent data:
| Structure | Used For |
|---|---|
| B⁺‑trees | Tables |
| B‑trees | Indexes |
No hash tables, no heap files, no clustered secondary structures. Every relation—whether a table or an index—gets its own tree.
Consequences
- Each tree corresponds to one relation or index.
- All trees live inside one database file.
- Pages from different trees can be interspersed on disk.
- No single page ever contains tuples from multiple trees.
That last point is crucial. Even though pages are shared at the file level, ownership is strict at the tree level. Enforcing this is one of the primary responsibilities of the tree module.
From Page‑Oriented to Tree‑Oriented
| Layer | What It Exposes |
|---|---|
| Pager | A collection of numbered pages |
| Tree Module | A tree‑oriented file supporting ordered access and tuple‑level insert, delete, and lookup |
Internally, the tree module:
- Chooses which pages belong to which tree
- Maintains parent/child relationships
- Ensures B⁺‑tree balance properties
- Decides when pages split or merge
To the pager, pages are just pages. To the tree module, pages are nodes.
The Tree Module Is Deliberately Passive
One subtle but important design choice: the tree module is structurally active but semantically passive.
| What it does care about | What it does not care about |
|---|---|
| Keys, ordering, page layout, tree balance, navigation | Column types, SQL schemas, constraints, meanings of fields inside a tuple |
It simply stores and retrieves variable‑length byte strings and keeps them in order. This separation of concerns allows SQLite’s VM to evolve independently of its storage engine.
Where Tree Metadata Lives
SQLite still needs a way to answer questions such as:
- Which tree belongs to which table?
- Where is the root page of this tree?
- Is this tree a table or an index?
That mapping information is stored in a special, well‑known relation:
sqlite_master(orsqlite_temp_masterfor temporary objects)
This catalog itself is stored in a predetermined B⁺‑tree, just like everything else. SQLite does not cheat by storing metadata “outside” the system—it eats its own dog food.
Where We’re Heading Next
So far, we’ve established the big picture:
- Pager → pages
- Tree module → tuples
- VM → SQL semantics
In the next few days we’ll zoom in further and get concrete:
- The Tree Interface Functions – how the VM actually talks to trees
- B⁺‑Tree Structure – interior nodes, leaf nodes, separators
- Page Structure – how tuples are packed, indexed, and navigated inside a single page
That’s where diagrams start making sense and the real elegance of SQLite’s design shows up.
Key idea to carry forward: SQLite turns a byte file into pages, pages into trees, and trees into relations—one clean layer at a time.
My experiments and hands‑on executions related to SQLite live here:
lovestaco/sqlite – sqlite‑examples
References
- SQLite Database System: Design and Implementation – Sibsankar Haldar
(replace with actual image URL if needed)
[](https://hexmos.com/freedevtools/)
👉 **Check out:** [FreeDevTools](https://hexmos.com/freedevtools/)
Any feedback or contributions are welcome!
It’s online, open‑source, and ready for anyone to use.
⭐ **Star it on GitHub:** [FreeDevTools repository](https://github.com/HexmosTech/FreeDevTools)