Libra Database Scheme
Introduction
Libra use sea-orm to interact with sqlite database. The data model is defined in libra/src/internal/model, with two tables: config and reference.
The config table is used to store the configuration of the project, which corresponds to the config file in git. The reference table is used to store the reference of the project, which corresponds to the HEAD and refs/* files in git. This reflog is used to record the history of changes to references, corresponding to the files in the .git/logs/ directory in git.
The relationship between the git file and the sqlite table is as follows:
reference:
| Category | Description | Database format |
|---|---|---|
| .git/HEAD | Current head pointer (branch or commit hash) | Reference(name=<branch>; kind=HEAD;commit=null;remote=null) Reference(name=null; kind=HEAD;commit= <commit hash>;remote=null) |
.git/refs/heads/<branch> | Branch name, can’t be “HEAD” | Reference(name=<branch>, kind=Branch; commit=<commit hash>; remote=null) |
.git/refs/tags/<tag> | Similar to branch | Reference(name=<tag>, kind=Tag; commit=<commit hash>; remote=null) |
.git/refs/remotes/<remote>/<branch> | Contains branch heads and HEADRemote HEAD can’t be detached. | Reference(name=<branch>, kind=Branch; commit=<commit hash>; remote=<remote>)Reference(name= <branch>; type=HEAD; commit=null; remote=<remote>) |
config:
# config Example
[core]
filemode = true
ignorecase = false
[remote "origin"]
url = url.git
fetch = +refs/heads……
| Category | Description | Database format |
|---|---|---|
.gitconfig | Ini format configuration | Config(configuration=”core”; name=null; key=”filemode”;value=”true” ) Config(configuration=”core”; name=null; key=”ignorecase”;value=”false” ) Config(configuration=”remote”; name=”origin”; key=”url”;value=”url.git” ) Config(configuration=”remote”; name=”null”; key=”fetch”;value=”+refs……” ) |
reflog:
The reflog table records every movement of the HEAD and branch references. Whenever a reference (like HEAD or refs/heads/main) is updated, a new record is inserted into this table to describe the change.
| Category | Description | Database format |
|---|---|---|
.git/logs/HEAD.git/logs/refs/heads/<branch> | Records the history of reference changes | Reflog( ref_name= <ref_name>,old_oid= <previous_hash>,new_oid= <new_hash>,committer_name= <name>,committer_email= <email>,timestamp= <unix_timestamp>,action= <action_type>,message= <description>) |
Business Model Design
For decoupling, the sea-orm model is not directly used in the code, and the business model is redefined (located in libra/src/internal), and common CRUD operations are implemented.
Currently, the config, reference and reflog models are implemented.
SQL Statement
CREATE TABLE IF NOT EXISTS `config` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`configuration` TEXT NOT NULL,
`name` TEXT,
`key` TEXT NOT NULL,
`value` TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS `reference` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
-- name can't be ''
`name` TEXT CHECK (name <> '' OR name IS NULL),
`kind` TEXT NOT NULL CHECK (kind IN ('Branch', 'Tag', 'Head')),
`commit` TEXT,
-- remote can't be ''. If kind is Tag, remote must be NULL.
`remote` TEXT CHECK (remote <> '' OR remote IS NULL),
CHECK (
(kind <> 'Tag' OR (kind = 'Tag' AND remote IS NULL))
)
);
CREATE TABLE IF NOT EXISTS `reflog` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`ref_name` TEXT NOT NULL,
`old_oid` TEXT NOT NULL,
`new_oid` TEXT NOT NULL,
`committer_name` TEXT NOT NULL,
`committer_email` TEXT NOT NULL,
`timestamp` INTEGER NOT NULL,
`action` TEXT NOT NULL,
`message` TEXT NOT NULL
);
-- (name, kind, remote) as unique key when remote is not null
CREATE UNIQUE INDEX idx_name_kind_remote ON `reference`(`name`, `kind`, `remote`)
WHERE `remote` IS NOT NULL;
-- (name, kind) as unique key when remote is null
CREATE UNIQUE INDEX idx_name_kind ON `reference`(`name`, `kind`)
WHERE `remote` IS NULL;
CREATE INDEX idx_ref_name_timestamp ON `reflog`(`ref_name`, `timestamp`);