diff --git a/dao/src/commonMain/kotlin/io/github/kdroidfilter/seforimlibrary/dao/repository/SeforimRepository.kt b/dao/src/commonMain/kotlin/io/github/kdroidfilter/seforimlibrary/dao/repository/SeforimRepository.kt index 75136b5e..0fe7fc08 100644 --- a/dao/src/commonMain/kotlin/io/github/kdroidfilter/seforimlibrary/dao/repository/SeforimRepository.kt +++ b/dao/src/commonMain/kotlin/io/github/kdroidfilter/seforimlibrary/dao/repository/SeforimRepository.kt @@ -1664,6 +1664,60 @@ class SeforimRepository(databasePath: String, private val driver: SqlDriver) : L forward + inverse } + /** + * The lines that the cross-reference links of [lineIds] point to: REFERENCE and MESORAT_HASHAS in + * both directions (these links are unoriented and stored once), EIN_MISHPAT forward only (its + * reverse is the SOURCE view). A line is returned once, however many links reach it; the lines of + * [lineIds] themselves are left out. + */ + suspend fun getReferencesForLines(lineIds: Collection): List = + withContext(Dispatchers.IO) { + if (lineIds.isEmpty()) return@withContext emptyList() + database.linkQueriesQueries.selectReferencesByLineIds(lineIds, lineIds) { + _, connectionType, fromLineId, lineId, bookId, lineIndex, heRef, content, bookTitle, categoryId, bookOrderIndex -> + lineReference(connectionType, fromLineId, lineId, bookId, lineIndex, heRef, content, bookTitle, categoryId, bookOrderIndex) + }.executeAsList() + .filter { it.line.id !in lineIds } + .distinctBy { it.line.id } + } + + /** + * The lines that [lineIds] comment on (the SOURCE view), as [getReferencesForLines] returns its + * lines, in the SOURCE view's order. A line is returned once, however many links reach it. + */ + suspend fun getSourcesForLines(lineIds: Collection): List = + withContext(Dispatchers.IO) { + if (lineIds.isEmpty()) return@withContext emptyList() + database.linkQueriesQueries.selectSourcesByLineIds(lineIds) { + _, _, fromLineId, lineId, bookId, lineIndex, heRef, content, bookTitle, categoryId, bookOrderIndex -> + lineReference( + ConnectionType.SOURCE.name, fromLineId, lineId, bookId, lineIndex, heRef, content, bookTitle, categoryId, + bookOrderIndex, + ) + }.executeAsList() + .distinctBy { it.line.id } + } + + private fun lineReference( + connectionType: String, + fromLineId: Long, + lineId: Long, + bookId: Long, + lineIndex: Long, + heRef: String?, + content: String, + bookTitle: String, + categoryId: Long, + bookOrderIndex: Long, + ) = LineReference( + connectionType = ConnectionType.fromString(connectionType), + fromLineId = fromLineId, + line = Line(id = lineId, bookId = bookId, lineIndex = lineIndex.toInt(), content = content, heRef = heRef), + bookTitle = bookTitle, + categoryId = categoryId, + bookOrderIndex = bookOrderIndex.toInt(), + ) + /** * Lightweight variant for prefetch/navigation use cases; omits target text content. * When [includeSources] is false (default), only forward links are returned — callers @@ -2984,3 +3038,14 @@ data class CommentarySummary( val link: Link, val targetBookTitle: String ) + +/** A line a cross-reference link reaches, with what its book's grouping needs. */ +data class LineReference( + val connectionType: ConnectionType, + /** The line of the request this link starts from. */ + val fromLineId: Long, + val line: Line, + val bookTitle: String, + val categoryId: Long, + val bookOrderIndex: Int, +) diff --git a/dao/src/commonMain/sqldelight/io/github/kdroidfilter/seforimlibrary/db/LinkQueries.sq b/dao/src/commonMain/sqldelight/io/github/kdroidfilter/seforimlibrary/db/LinkQueries.sq index ee7bde23..fc19b2e7 100644 --- a/dao/src/commonMain/sqldelight/io/github/kdroidfilter/seforimlibrary/db/LinkQueries.sq +++ b/dao/src/commonMain/sqldelight/io/github/kdroidfilter/seforimlibrary/db/LinkQueries.sq @@ -343,3 +343,37 @@ WHERE l.targetBookId = ? AND l.sourceBookId != l.targetBookId GROUP BY l.sourceBookId, b.title, a.name ORDER BY MAX(l.isDeclaredBase) DESC, b.isBaseBook DESC, b.orderIndex, b.title; + +-- The cross-reference links of lines: the line on the other side of each link, with its book. +-- REFERENCE and MESORAT_HASHAS are unoriented (stored once): both directions. EIN_MISHPAT runs from +-- a line to the codes that rule on it: forward only, its reverse being the SOURCE view. +selectReferencesByLineIds: +SELECT l.id AS linkId, ct.name AS connectionType, l.sourceLineId AS fromLineId, ol.id AS lineId, ol.bookId, ol.lineIndex, ol.heRef, ol.content, + b.title AS bookTitle, b.categoryId, b.orderIndex AS bookOrderIndex +FROM link l +JOIN connection_type ct ON l.connectionTypeId = ct.id +JOIN line ol ON ol.id = l.targetLineId +JOIN book b ON b.id = ol.bookId +WHERE ct.name IN ('REFERENCE', 'MESORAT_HASHAS', 'EIN_MISHPAT') AND l.sourceLineId IN ? +UNION ALL +SELECT l.id AS linkId, ct.name AS connectionType, l.targetLineId AS fromLineId, ol.id AS lineId, ol.bookId, ol.lineIndex, ol.heRef, ol.content, + b.title AS bookTitle, b.categoryId, b.orderIndex AS bookOrderIndex +FROM link l +JOIN connection_type ct ON l.connectionTypeId = ct.id +JOIN line ol ON ol.id = l.sourceLineId +JOIN book b ON b.id = ol.bookId +WHERE ct.name IN ('REFERENCE', 'MESORAT_HASHAS') AND l.targetLineId IN ?; + +-- The SOURCE view of lines in the shape of selectReferencesByLineIds: the lines these lines comment +-- on, with their book, in the SOURCE view's order (declared bases first, then base books, then catalog). +selectSourcesByLineIds: +SELECT l.id AS linkId, ct.name AS connectionType, l.targetLineId AS fromLineId, ol.id AS lineId, ol.bookId, ol.lineIndex, ol.heRef, ol.content, + b.title AS bookTitle, b.categoryId, b.orderIndex AS bookOrderIndex +FROM link l +JOIN connection_type ct ON l.connectionTypeId = ct.id +JOIN line ol ON ol.id = l.sourceLineId +JOIN book b ON b.id = ol.bookId +WHERE l.targetLineId IN ? + AND ct.name IN ('COMMENTARY','SUPER_COMMENTARY','TARGUM','MIDRASH','PARSHANUT','DIBUR_HAMATCHIL','EIN_MISHPAT') + AND l.sourceBookId != l.targetBookId +ORDER BY l.isDeclaredBase DESC, b.isBaseBook DESC, b.orderIndex, ol.lineIndex;