feat(schema): subtitle/explicit columns, authors+publishers arrays, float series numbers

Phase 1 of the series/collections/metadata overhaul
(~/.opencode/plan/series-collections-metadata-overhaul.md).

Schema (in place, idempotent):
- media_items.series_number INTEGER -> DOUBLE PRECISION: real-world
  ordinals are decimals (0.5, 1.5 novellas); INTEGER silently truncated
  them (calibre 2.5 pinned as 2 in tests).
- + subtitle TEXT, explicit BOOLEAN (sidecar ingest; ABS explicit /
  Audible isAdult).
- + authors/authors_search/publishers/publishers_search TEXT[] NOT NULL
  (narrators A2a precedent). Arrays are write truth; author/publisher
  varchars become trigger-regenerated display strings
  (sync_author_publisher_display) so every varchar consumer (trgm
  search, facets, API, OPDS/Kobo) keeps working unchanged.
- Row-level NULL normalization for the new arrays in
  set_library_type_name (A2 lesson: Go nil -> explicit NULL -> 23502).
- Backfills ARRAY[author]/ARRAY[publisher] — deliberately no
  comma-splitting ('Tolkien, J.R.R.' would corrupt; scanner kept only
  authors[0] historically).
- collection_items.position INTEGER + (collection_id, position) index
  for playlist ordering.

Go: sqlc regen; MediaMetadata/handler params gain Subtitle/Explicit/
Authors/Publishers (legacy singles still accepted, arrays win);
SeriesNumber int32 -> float64 end to end; metadata_overrides adapted
with legacy override keys ('author'/'publisher') preserved so existing
user overrides survive; bulk author edit writes the array.

Pins widened (docs/contract_pins.md): raw sqlc row key set + the six
new columns; changelog entry added.

Verified: unit suite green; integration sweep (bulk/smart collections/
scanner/stats/sync/queue/calibre/pins/audiobooks) green against the
shared dev DB after in-place migration. Pre-existing unrelated red:
TestOwnershipAndAdminTestSuite/TestAdminCreateUser timezone inheritance
fails identically at the pre-change commit (live shared state).
This commit is contained in:
John O'Keefe committed 2026-10-19 14:17:50 -04:00
1 parent f7dc8189a1
commit 646477afad
30 files changed
+790 -247

No files matched your search

+3 -3
View File
@@ -537,15 +537,15 @@ func BookDetail(user User, book handlers.MediaDetail, errorMessage string, tombs
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
if book.SeriesNumber.Valid && book.SeriesNumber.Int32 > 0 {
if book.SeriesNumber.Valid && book.SeriesNumber.Float64 > 0 {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 57, "#")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var26 string
templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(book.SeriesNumber.Int32)
templ_7745c5c3_Var26, templ_7745c5c3_Err = templ.JoinStringErrs(fmtNumber(book.SeriesNumber.Float64))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 195, Col: 37}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `book_detail.templ`, Line: 195, Col: 50}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var26))
if templ_7745c5c3_Err != nil {