Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,19 @@ fun io.github.kdroidfilter.seforimlibrary.db.SelectByLineId.toModel(): TocEntry
)
}

fun io.github.kdroidfilter.seforimlibrary.db.SelectAncestorPath.toModel(): TocEntry =
TocEntry(
id = id,
bookId = bookId,
parentId = parentId,
textId = textId,
text = text,
level = level.toInt(),
lineId = lineId,
isLastChild = isLastChild == 1L,
hasChildren = hasChildren == 1L
)

// --- Alternative TOC mappings ---

fun io.github.kdroidfilter.seforimlibrary.db.Alt_toc_structure.toModel(): AltTocStructure =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package io.github.kdroidfilter.seforimlibrary.dao.repository

import io.github.kdroidfilter.seforimlibrary.core.models.Line
import io.github.kdroidfilter.seforimlibrary.core.models.TocEntry

/**
* Interface for line selection and navigation related repository operations.
* This interface is extracted to allow mocking in tests.
*/
interface LineSelectionRepository {
/**
* Returns the TOC entry whose heading line is the given line id, or null if not a TOC heading.
*/
suspend fun getHeadingTocEntryByLineId(lineId: Long): TocEntry?

/**
* Returns all line ids that belong to the given TOC entry (section), ordered by lineIndex.
*/
suspend fun getLineIdsForTocEntry(tocEntryId: Long): List<Long>

/**
* Returns the TOC entry ID for a given line, or null if the line has no TOC mapping.
*/
suspend fun getTocEntryIdForLine(lineId: Long): Long?

/**
* Returns a TOC entry by its ID.
*/
suspend fun getTocEntry(id: Long): TocEntry?

/**
* Returns the ancestor path from the given TOC entry up to the root, ordered by level ASC.
*/
suspend fun getAncestorPath(tocId: Long): List<TocEntry>

/**
* Returns a line by its ID.
*/
suspend fun getLine(id: Long): Line?

/**
* Returns the previous line in the book, or null if at the beginning.
*/
suspend fun getPreviousLine(bookId: Long, currentLineIndex: Int): Line?

/**
* Returns the next line in the book, or null if at the end.
*/
suspend fun getNextLine(bookId: Long, currentLineIndex: Int): Line?

/**
* Returns lines in a range for a book.
*/
suspend fun getLines(bookId: Long, startIndex: Int, endIndex: Int): List<Line>
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,16 @@ class SeforimRepository(databasePath: String, private val driver: SqlDriver) {
} catch (e: Exception) {
logger.d{"Error counting books: ${e.message}"}
}

// Warm up SQLite page cache by touching the line table index
try {
driver.executeQuery(
null,
"SELECT COUNT(*) FROM line WHERE bookId = 1",
{ c -> QueryResult.Value(if (c.next().value) c.getLong(0) else 0L) },
0,
)
} catch (_: Exception) { }
}


Expand Down Expand Up @@ -1158,6 +1168,14 @@ class SeforimRepository(databasePath: String, private val driver: SqlDriver) {
database.tocQueriesQueries.selectChildren(parentId).executeAsList().map { it.toModel() }
}

override suspend fun getAncestorPath(tocId: Long): List<TocEntry> = withContext(Dispatchers.IO) {
database.tocQueriesQueries.selectAncestorPath(tocId).executeAsList().map { it.toModel() }
}

suspend fun getFirstLeafTocId(tocId: Long): Long? = withContext(Dispatchers.IO) {
database.tocQueriesQueries.selectFirstLeafUnder(tocId).executeAsOneOrNull()
}

// --- Alternative TOC structures ---

suspend fun getAltTocStructuresForBook(bookId: Long): List<AltTocStructure> = withContext(Dispatchers.IO) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,29 @@ deleteByBookId:
DELETE FROM tocEntry WHERE bookId = ?;

lastInsertRowId:
SELECT last_insert_rowid();
SELECT last_insert_rowid();

selectAncestorPath:
WITH RECURSIVE ancestors(id, bookId, parentId, textId, level, lineId, isLastChild, hasChildren) AS (
SELECT id, bookId, parentId, textId, level, lineId, isLastChild, hasChildren
FROM tocEntry WHERE id = ?
UNION ALL
SELECT t.id, t.bookId, t.parentId, t.textId, t.level, t.lineId, t.isLastChild, t.hasChildren
FROM tocEntry t
JOIN ancestors a ON t.id = a.parentId
)
SELECT a.*, tt.text
FROM ancestors a
JOIN tocText tt ON a.textId = tt.id
ORDER BY a.level ASC;

selectFirstLeafUnder:
WITH RECURSIVE descent(id, hasChildren) AS (
SELECT id, hasChildren FROM tocEntry WHERE id = ?
UNION ALL
SELECT (SELECT t.id FROM tocEntry t WHERE t.parentId = d.id ORDER BY t.id LIMIT 1),
(SELECT t.hasChildren FROM tocEntry t WHERE t.parentId = d.id ORDER BY t.id LIMIT 1)
FROM descent d
WHERE d.hasChildren = 1
)
SELECT id FROM descent WHERE hasChildren = 0 LIMIT 1;
Loading