Skip to content

Commit f06a5ea

Browse files
committed
feat(book): add heRef property for stable Hebrew reference identification
- Add heRef column to book table with index for efficient lookups - Update Book model with heRef property and KDoc documentation - Add selectByHeRef query and getBookByHeRef repository method - Update insert queries to include heRef parameter - Set heRef from title in Otzaria generator - Set heRef from heTitle in Sefaria generator This allows stable identification of books across database regenerations, similar to how line.heRef works for lines.
1 parent f7f0faa commit f06a5ea

File tree

7 files changed

+30
-4
lines changed

7 files changed

+30
-4
lines changed

core/src/commonMain/kotlin/io/github/kdroidfilter/seforimlibrary/core/models/Book.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import kotlinx.serialization.Serializable
99
* @property id The unique identifier of the book
1010
* @property categoryId The identifier of the category this book belongs to
1111
* @property title The title of the book
12+
* @property heRef A stable Hebrew reference identifier for the book, used for consistent identification
13+
* across database regenerations (e.g., "בראשית", "רש״י על בראשית")
1214
* @property sourceId The identifier of the source this book originates from
1315
* @property authors The list of authors of this book
1416
* @property topics The list of topics associated with this book
@@ -28,6 +30,7 @@ data class Book(
2830
val categoryId: Long,
2931
val sourceId: Long,
3032
val title: String,
33+
val heRef: String? = null,
3134
val authors: List<Author> = emptyList(),
3235
val topics: List<Topic> = emptyList(),
3336
val pubPlaces: List<PubPlace> = emptyList(),

dao/src/commonMain/kotlin/io/github/kdroidfilter/seforimlibrary/dao/extensions/ModelExtensions.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ fun io.github.kdroidfilter.seforimlibrary.db.Book.toModel(json: Json, authors: L
7878
categoryId = categoryId,
7979
sourceId = sourceId,
8080
title = title,
81+
heRef = heRef,
8182
authors = authors,
8283
topics = emptyList(),
8384
pubPlaces = pubPlaces,

dao/src/commonMain/kotlin/io/github/kdroidfilter/seforimlibrary/dao/repository/SeforimRepository.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,19 @@ class SeforimRepository(databasePath: String, private val driver: SqlDriver) {
641641
return@withContext bookData.toModel(json, authors, pubPlaces, pubDates).copy(topics = topics)
642642
}
643643

644+
/**
645+
* Retrieves a book by its stable Hebrew reference identifier (heRef).
646+
* Returns null if no book with the given heRef exists.
647+
*/
648+
suspend fun getBookByHeRef(heRef: String): Book? = withContext(Dispatchers.IO) {
649+
val bookData = database.bookQueriesQueries.selectByHeRef(heRef).executeAsOneOrNull() ?: return@withContext null
650+
val authors = getBookAuthors(bookData.id)
651+
val topics = getBookTopics(bookData.id)
652+
val pubPlaces = getBookPubPlaces(bookData.id)
653+
val pubDates = getBookPubDates(bookData.id)
654+
return@withContext bookData.toModel(json, authors, pubPlaces, pubDates).copy(topics = topics)
655+
}
656+
644657
/**
645658
* Retrieves a book by approximate title (exact, normalized, or LIKE).
646659
*/
@@ -852,6 +865,7 @@ class SeforimRepository(databasePath: String, private val driver: SqlDriver) {
852865
categoryId = book.categoryId,
853866
sourceId = book.sourceId,
854867
title = book.title,
868+
heRef = book.heRef,
855869
heShortDesc = book.heShortDesc,
856870
notesContent = book.notesContent,
857871
orderIndex = book.order.toLong(),
@@ -909,6 +923,7 @@ class SeforimRepository(databasePath: String, private val driver: SqlDriver) {
909923
categoryId = book.categoryId,
910924
sourceId = book.sourceId,
911925
title = book.title,
926+
heRef = book.heRef,
912927
heShortDesc = book.heShortDesc,
913928
notesContent = book.notesContent,
914929
orderIndex = book.order.toLong(),

dao/src/commonMain/sqldelight/io/github/kdroidfilter/seforimlibrary/db/BookQueries.sq

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,15 @@ selectBaseIds:
4040
SELECT id FROM book WHERE isBaseBook = 1 ORDER BY orderIndex, title;
4141

4242
insert:
43-
INSERT INTO book (categoryId, sourceId, title, heShortDesc, notesContent, orderIndex, totalLines, isBaseBook, hasSourceConnection, hasAltStructures, hasTeamim, hasNekudot)
44-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
43+
INSERT INTO book (categoryId, sourceId, title, heRef, heShortDesc, notesContent, orderIndex, totalLines, isBaseBook, hasSourceConnection, hasAltStructures, hasTeamim, hasNekudot)
44+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
4545

4646
insertWithId:
47-
INSERT INTO book (id, categoryId, sourceId, title, heShortDesc, notesContent, orderIndex, totalLines, isBaseBook, hasSourceConnection, hasAltStructures, hasTeamim, hasNekudot)
48-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
47+
INSERT INTO book (id, categoryId, sourceId, title, heRef, heShortDesc, notesContent, orderIndex, totalLines, isBaseBook, hasSourceConnection, hasAltStructures, hasTeamim, hasNekudot)
48+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);
49+
50+
selectByHeRef:
51+
SELECT * FROM book WHERE heRef = ? LIMIT 1;
4952

5053
updateTotalLines:
5154
UPDATE book SET totalLines = ? WHERE id = ?;

dao/src/commonMain/sqldelight/io/github/kdroidfilter/seforimlibrary/db/Database.sq

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ CREATE TABLE IF NOT EXISTS book (
6969
categoryId INTEGER NOT NULL,
7070
sourceId INTEGER NOT NULL,
7171
title TEXT NOT NULL,
72+
heRef TEXT,
7273
heShortDesc TEXT,
7374
-- Optional raw notes attached to the base book (when a companion file 'הערות על <title>' exists)
7475
notesContent TEXT,
@@ -91,6 +92,7 @@ CREATE INDEX IF NOT EXISTS idx_book_category ON book(categoryId);
9192
CREATE INDEX IF NOT EXISTS idx_book_title ON book(title);
9293
CREATE INDEX IF NOT EXISTS idx_book_order ON book(orderIndex);
9394
CREATE INDEX IF NOT EXISTS idx_book_source ON book(sourceId);
95+
CREATE INDEX IF NOT EXISTS idx_book_heref ON book(heRef);
9496

9597
-- Book-publication place junction table
9698
CREATE TABLE IF NOT EXISTS book_pub_place (

generator/otzariasqlite/src/commonMain/kotlin/io/github/kdroidfilter/seforimlibrary/otzariasqlite/Generator.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,7 @@ class DatabaseGenerator(
728728
categoryId = categoryId,
729729
sourceId = sourceId,
730730
title = title,
731+
heRef = title,
731732
authors = authors,
732733
pubPlaces = pubPlaces,
733734
pubDates = pubDates,

generator/sefariasqlite/src/jvmMain/kotlin/io/github/kdroidfilter/seforimlibrary/sefariasqlite/SefariaDirectImporter.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ class SefariaDirectImporter(
174174
categoryId = catId,
175175
sourceId = sourceId,
176176
title = payload.heTitle,
177+
heRef = payload.heTitle,
177178
authors = payload.authors.map { Author(name = it) },
178179
pubPlaces = emptyList(),
179180
pubDates = payload.pubDates,

0 commit comments

Comments
 (0)