|
9 | 9 | from sqlalchemy import event, Column, Text, Computed |
10 | 10 | from sqlalchemy.sql import func |
11 | 11 | # from sqlalchemy.dialects.mysql import LONGTEXT |
12 | | -from sqlalchemy.orm import relationship |
| 12 | +from sqlalchemy.orm import relationship, validates |
13 | 13 | from sqlalchemy.dialects.postgresql import TSVECTOR |
14 | 14 | from pgvector.sqlalchemy import Vector |
15 | 15 | # from sqlalchemy_fulltext import FullText |
@@ -75,6 +75,7 @@ class Mark(db.Model): |
75 | 75 |
|
76 | 76 | valid_types = ['bookmark', 'feed', 'youtube'] |
77 | 77 | valid_feed_types = ['feed', 'youtube'] |
| 78 | + max_title_length = 255 |
78 | 79 |
|
79 | 80 | def __init__(self, owner_id: int, created: dt | None = None) -> None: |
80 | 81 | """ |
@@ -123,6 +124,18 @@ def insert_from_import(self, data: dict[str, Any]) -> None: |
123 | 124 | def __repr__(self) -> str: |
124 | 125 | return f'<Mark {self.title!r}>' |
125 | 126 |
|
| 127 | + @staticmethod |
| 128 | + def clamp_title_length(value: Any) -> str | None: |
| 129 | + """Ensure titles always fit in the DB column constraint.""" |
| 130 | + if value is None: |
| 131 | + return None |
| 132 | + return str(value)[:Mark.max_title_length] |
| 133 | + |
| 134 | + @validates('title') |
| 135 | + def validate_title_length(self, key: str, value: Any) -> str | None: |
| 136 | + """Clamp title before any insert/update so DB writes cannot overflow.""" |
| 137 | + return self.clamp_title_length(value) |
| 138 | + |
126 | 139 | def get_embedding_text(self) -> str: |
127 | 140 | """ |
128 | 141 | Generate the text to be embedded for this mark. |
|
0 commit comments