# Database Schema & the comp_id Model
db/sggs.sqlite (~104 MiB, Git LFS) is opened read-only (mode=ro&immutable=1, queryonly). 33 real tables + FTS5 shadow tables, in five layers.
- Page:
- Updated: 2026-10-27
- Pinned copy of `Algorythmos-AI/sggs-data` `docs/architecture/database-schema.md` at `c36e317`; the canonical file is
- From the Sri Guru Granth Sahib Ji — Knowledge Base wiki. Sri Guru Granth Sahib Ji is quoted verbatim, cited by Ang, and never altered.
---
`db/sggs.sqlite` (~104 MiB, Git LFS) is opened read-only (`mode=ro&immutable=1`,
`query_only`). 33 real tables + FTS5 shadow tables, in five layers.
## `lines` — the verse table (60,658 rows)
One display line each: `id`, `ang` (1–1430), `pdf_page`, `raag`, `section`,
`author`, `comp_type`, `ghar`, **`comp_id`**, `line_no`, `is_rahao`, `is_header`,
`markers`, `gurmukhi` (verbatim), `text` (clean), `translit`, `translit_norm`
(phonetic fold, DB-built), `fl_g`/`fl_r`, `skeleton`, `stanza_index`, `pada_total`,
`source_category`.
## `comp_id` groups a whole composition — heading run included
A composition (a shabad, salok, pauri, vaar unit) is the set of `lines` sharing a
`comp_id`. **A run of consecutive heading lines opens ONE composition together with
the body it introduces** — a raag/title line, the `ੴ` invocation, and a
`ਸਲੋਕੁ ਮਃ` label all carry the same `comp_id` as the verses they precede.
```mermaid
flowchart TB
accTitle: comp_id before and after v1.1.0
accDescr: Before v1.1.0 a heading line and the invocation after it each had their own comp_id, orphaned from the composition they open; since v1.1.0 the heading run shares the comp_id of the composition, and the vacated ids stay gaps.
subgraph before["Before v1.1.0 (the bug)"]
t1["ਟੋਡੀ ਮਹਲਾ ੫ ਘਰੁ ੨ ਚਉਪਦੇ · comp 2844 (orphan)"]
i1["ੴ ਸਤਿਗੁਰ ਪ੍ਰਸਾਦਿ · comp 2845"]
v1["verses… · comp 2845"]
i1 --- v1
end
subgraph after["v1.1.0 (fixed)"]
t2["ਟੋਡੀ ਮਹਲਾ ੫ ਘਰੁ ੨ ਚਉਪਦੇ · comp 2845"]
i2["ੴ ਸਤਿਗੁਰ ਪ੍ਰਸਾਦਿ · comp 2845"]
v2["verses… · comp 2845"]
t2 --- i2 --- v2
end
```
Before v1.1.0 every heading line got its own `comp_id`, so a title line followed
by a separate `ੴ` invocation became a one-line "orphan" composition that
`/api/shabad/{comp_id}` never fetched — the sheet dropped the printed title. The
fix (`build_corpus.py` post-pass 1b) folds each heading run into the composition it
opens.
### Key invariants (checked by `verify_regroup.py`)
- The run adopts its **last** heading's `comp_id` → **no body line's `comp_id`
ever changes**, so saved bookmarks, deep links, and analytics keyed on `comp_id`
stay valid.
- Vacated ids become **permanent gaps**: distinct compositions **4,527**,
`max(comp_id)` **5,376** (since the v1.1.4 build, which demoted 233 verses mis-flagged as
headings and burned the ids they had opened; `pipeline/tests/test_docs_facts.py` holds these
numbers to the database). `comp_id` 1 is a gap (Mool Mantar folds into Japji, `comp_id` 2).
`/api/shabad/{gap}` → 404.
- Every composition's first line is a heading; no heading follows a body line.
- Exactly **3** header-only compositions remain — the closing rubrics `ਜੁਮਲਾ`,
`ਦੁਤੁਕੇ`, `ਏਹੁ ਸਲੋਕੁ ਆਦਿ ਅੰਤਿ ਪੜਣਾ` (`TRAILING_RUBRICS`), which belong to the
*preceding* unit and are flagged for scholarly review.
## Layers (grouped)
- **Scripture core:** `lines`, `raags`, `sections`, `authors`, `vaars`, `vaar_units`, `shabd_raag_map`, `shabd_musical_markers`, `shabd_structural_form`, `shabd_poetic_genre`.
- **Search:** `fts`, `fts_en`, `fts_shabad`, `fts_tri`, `variants`, `word_freq`, `canon_tokens`.
- **Translations:** `translations`, `sources`.
- **Analytics:** `concepts`, `concept_lines`, `theme_network`, `theme_fingerprint`, `author_analytics`, `raag_analytics`, `author_distinctive_terms`, `author_resonance`, `line_neighbors`, `shabad_neighbors`.
- **Knowledge / meta:** `raag_timing_claims`, `timing_sources`, `timing_migrations`, `meta`, `analytics_meta`.
## Gotchas
- `comp_type` is known-mislabeled in places; it is suppressed at the display layer. Prefer `comp_id`/`section`.
- `author` comes from the printed evidence (headings, ਮਃ labels, pen-names, shabad numbering) via the
attribution post-pass; see [attribution.md](https://docs.gurbanisoul.com/data/architecture/attribution/). Japji is Guru Nanak Dev Ji's (ledger entry
`japji`); contested attributions (Mardana, Raagmala, Bhatt splits, Surdas) are recorded, not changed.
- `line_neighbors` is built with a nondeterministic random projection — its row *order* varies across rebuilds (its content is what matters).