# Datenbank-Migrationen Manuelle Schritte, die beim Deploy gegen eine **bestehende** Datenbank nötig sind. Eine frische DB (Schema aus `db.go`) braucht keine davon. --- ## `avatar`-Spalte in `user` **Wann:** beim Deploy der Profilbild-Version gegen eine bestehende `kver.db`. **Hintergrund:** Profilbilder werden als Pfad (`static/media/...`) in der neuen Spalte `user.avatar` gespeichert (leerer String = kein Bild, Frontend zeigt dann das Platzhalterbild). `CREATE TABLE IF NOT EXISTS` ergänzt die Spalte bei einer vorhandenen Tabelle nicht. **Migration:** ```sql ALTER TABLE user ADD COLUMN avatar TEXT NOT NULL DEFAULT ''; ``` Bestehende Nutzer haben damit kein Bild (`''`). Nur einmalig ausführen. --- ## `filepath` NULL → leerer String **Wann:** beim Umstieg auf die Go-Version, falls `entry.filepath` NULL-Werte enthält. **Hintergrund:** `scanEntries` scannt `filepath` in ein Go-`string`-Feld (kein Pointer). SQLite NULL in ein `string` scannen schlägt fehl; `scanEntries` überspringt diese Zeilen still mit `continue`. Ergebnis: Einträge ohne Bild fehlen im Feed komplett. Das aktuelle Go-Schema definiert `filepath TEXT NOT NULL DEFAULT ''`. `migrate.sh` normalisiert NULL → `''` beim Kopieren aus der Quelldatenbank. ```sql UPDATE entry SET filepath = '' WHERE filepath IS NULL; ``` --- ## `filepath`-Sentinel `"none"` → leerer String **Wann:** beim Umstieg auf die Go-Version, falls eine alte `kver.db` aus der Python-Zeit weiterverwendet wird. **Hintergrund:** Die Python-Version schrieb für Beiträge ohne Bild den String `"none"` in `entry.filepath`. Die Go-Version nutzt stattdessen den leeren String (Go-Zero-Value) und prüft nur noch auf `filepath == ""`. Alte `"none"`-Zeilen würden sonst im Feed als Bildpfad interpretiert (`` → kaputtes Bild). **Migration:** ```sql UPDATE entry SET filepath = '' WHERE filepath = 'none'; ``` Idempotent — kann gefahrlos mehrfach laufen. --- ## Threading-Spalten in `entry` **Wann:** beim Deploy der Threading-Version gegen eine bestehende `kver.db`, die die Tabelle `entry` noch ohne die Threading-Spalten hat. **Hintergrund:** Das Threading führt `reply_to` (pid des Eltern-Posts, `0` = Root), `reply_count` (Anzahl Antworten im gesamten Teilbaum) und `last_activity` (Sortierschlüssel des Hauptfeeds) ein. `CREATE TABLE IF NOT EXISTS` ergänzt diese Spalten bei einer vorhandenen Tabelle nicht. **Migration:** ```sql ALTER TABLE entry ADD COLUMN reply_to INTEGER NOT NULL DEFAULT 0; ALTER TABLE entry ADD COLUMN reply_count INTEGER NOT NULL DEFAULT 0; ALTER TABLE entry ADD COLUMN last_activity INTEGER; UPDATE entry SET last_activity = created_at WHERE last_activity IS NULL; ``` Bestehende Zeilen werden so zu Root-Beiträgen (`reply_to = 0`, `reply_count = 0`) mit `last_activity = created_at`. Nicht idempotent — die `ALTER TABLE`-Zeilen nur einmalig ausführen. --- ## Soft-Delete-Spalte in `entry` **Wann:** beim Deploy der Soft-Delete-Version gegen eine bestehende `kver.db`. **Hintergrund:** Statt Beiträge hart zu löschen werden sie als `[deleted]`-Platzhalter markiert (`deleted = 1`, Inhalt/Bild/Autor geleert), damit Antworten nicht verwaisen. Das Frontend und die Feeds erkennen gelöschte Beiträge an dieser Spalte. **Migration:** ```sql ALTER TABLE entry ADD COLUMN deleted INTEGER NOT NULL DEFAULT 0; ``` Bestehende Beiträge bleiben damit sichtbar (`deleted = 0`). Nur einmalig ausführen. --- ## `asn`-Spalte in `impression` **Wann:** beim Deploy der ASN-Auswertung gegen eine bestehende `impression`-Tabelle. **Hintergrund:** Pro Impression wird das autonome System (Netzbetreiber) gespeichert, aufgelöst aus der vollen Client-IP *vor* dem Maskieren (siehe `lookupASN`). Die Spalte liegt bewusst **nicht** im Primärschlüssel — pro `anon_ip` ist das ASN deterministisch, also entstehen keine Zeilen-Duplikate, und ein simples `ADD COLUMN` genügt (kein Tabellen-Rebuild). `CREATE TABLE IF NOT EXISTS` ergänzt die Spalte bei einer vorhandenen Tabelle nicht. **Migration:** ```sql ALTER TABLE impression ADD COLUMN asn TEXT NOT NULL DEFAULT ''; ``` Bestehende Zeilen haben damit kein ASN (`''`, in der Auswertung „(unbekannt)"). Nur einmalig ausführen.