Skip to content

עוגני-מילה לקישורים: טבלת link_anchor + מילוי בשני הגנרטורים#13

Closed
Y-PLONI wants to merge 0 commit into
otzariafrom
word-level-link-anchors
Closed

עוגני-מילה לקישורים: טבלת link_anchor + מילוי בשני הגנרטורים#13
Y-PLONI wants to merge 0 commit into
otzariafrom
word-level-link-anchors

Conversation

@Y-PLONI

@Y-PLONI Y-PLONI commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

עוגני-מילה לקישורים: טבלת link_anchor + מילוי בשני הגנרטורים.

מה זה

עד היום קישור מעוגן לשורה שלמה. חלק מהמפרשים (למשל באר הגולה על שו"ע) מציבים כמה הערות על שורה אחת בלי דיבור-המתחיל, כך שאי אפשר לדעת על איזו מילה כל הערה. השינוי מוסיף עיגון ברמת המילה.

הטבלה

link_anchor(linkId, side, charStart, charEnd, label) — אופסטים במוסכמת תווים-גלויים (כמו line.charCount). מפתח ראשי מורכב על עמודות יציבות ⇒ אין שינוי ל-IdAllocator/buildstate ואין מיגרציה. נרשמה ל-PATCH_TABLES_IN_FK_ORDER ול-LogicalContentHasher כך שה-delta הקיים נושא אותה אוטומטית ל-DB של לקוחות.

מקורות העיגון

  1. itags של ספריא (<i data-commentator … data-order/data-label>) המוטמעים בטקסטי הבסיס — SefariaInlineAnchors. הסמנטיקה אומתה מול קוד הקליינט של ספריא; עוגן נוצר רק כשכבר קיימת שורת link תואמת, כך ששגיאת רזולוציה לא ממציאה קישור. תגים ללא data-label שומרים toGematria(order) כאות המודפסת.
  2. start/end בקבצי הקישורים של אוצריא (משפחת "אור הישר", ומשנה ברורה→שער הציון לאחר המרה) — נקראים ב-Generator ומומרים לאופסט תווים-גלויים; האות נגזרת מ-heRef_2 העשיר.
  3. charLevelData (quotation finder) מעמודות ה-CSV החדשות — SefariaCharLevelAnchors, ייבוא מדויק-בלבד: שער גרסה-יחידה תואמת + שורה שלא שונתה ע"י cleanSefariaLine + גבולות. תאים מבוססי-מילים מדולגים. כל דילוג נספר ומדווח.

אימות

  • טסטי יחידה חדשים (itags, גימטריה, בניית ref, פרסור charLevelData, שערי דיוק).
  • ריצת גנרטור מלאה על מיני-ייצוא אמיתי (בראשית + צרור המור, 705 שורות CSV): 704 עוגני ציטוט, כל חיתוך נוחת בדיוק על הפסוק המצוטט.
  • הצד המשלים (רינדור האות/הטווח) מומש ב-otzaria.

🤖 Generated with Claude Code

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for word-level link anchors (LinkAnchor) inside line text, adding a new database table, queries, and repository methods. It updates both the Otzaria and Sefaria SQLite generators to parse, convert, and import these anchors (using visible-character offsets) from inline commentary markers (itags) and char-level data, backed by comprehensive tests. The review feedback highlights two critical N+1 query performance bottlenecks in SefariaInlineAnchors and SefariaCharLevelAnchors due to repeated database calls inside loops, suggesting pre-fetching links into memory to optimize generation speed.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

var anchored = false
for (entry in entries) {
val tgtLineId = lineKeyToId[entry.path to (entry.lineIndex - 1)] ?: continue
for (linkId in repository.getLinkIdsBetweenLines(srcLineId, tgtLineId)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

יש כאן בעיית ביצועים משמעותית של N+1 שאילתות. הקריאה ל-repository.getLinkIdsBetweenLines(srcLineId, tgtLineId) מתבצעת בתוך לולאה מקוננת עמוקה עבור כל itag בכל שורה של כל ספר. עבור ספרים גדולים עם הרבה הערות שוליים (כמו שולחן ערוך), זה יגרום לעשרות אלפי שאילתות בודדות ל-DB, מה שיאט מאוד את תהליך הגנרציה.\n\nהצעה לפתרון:\nניתן לייעל זאת משמעותית על ידי טעינה מראש (pre-fetching) של כל הקישורים עבור הספר הנוכחי לתוך Map בזיכרון בתחילת הלולאה של הספר:\n1. הוספת מתודה ב-SeforimRepository שטוענת את כל הקישורים עבור sourceBookId מסוים (השאילתה selectLinksBySourceBook כבר קיימת ב-LinkQueries.sq).\n2. בניית Map מקומי של Pair(sourceLineId, targetLineId) -> List<Long> בתחילת הלולאה של book.\n3. שימוש ב-Map המקומי במקום פנייה ל-DB בכל איטרציה.

skip("offsets out of bounds")
continue
}
val linkIds = repository.getLinkIdsBetweenLines(entry.srcLineId, entry.tgtLineId)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

גם כאן ישנה בעיית ביצועים של N+1 שאילתות: הקריאה ל-repository.getLinkIdsBetweenLines(entry.srcLineId, entry.tgtLineId) מתבצעת בתוך לולאה על כל ה-pending (שיכול להכיל מאות אלפי איברים בריצה מלאה). פנייה ל-DB עבור כל איבר בנפרד תאט מאוד את הגנרטור.\n\nהצעה לפתרון:\nניתן לקבץ (group) את ה-pending לפי הספר (או ה-path), ולטעון מראש את הקישורים הרלוונטיים עבור אותו ספר לתוך Map בזיכרון, בדומה להצעה ב-SefariaInlineAnchors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant