diff --git a/server/pruef-material.mjs b/server/pruef-material.mjs index 81c8445e..cf3aedb0 100644 --- a/server/pruef-material.mjs +++ b/server/pruef-material.mjs @@ -524,6 +524,52 @@ const IN10 = tagLokal(10); + (fehlend.length ? ` -- es fehlt: ${fehlend.join(", ")}` : "")); } +melde(""); +melde("=== 9a. Die Umstellung merkt, wenn sie nicht durchkam ==="); +{ + /* WARUM DAS HIER STEHT: Im ersten Entwurf setzte `tabellen()` den + Vermerk "erledigt" UNBEDINGT -- auch wenn das ALTER scheiterte, + dessen Fehler daneben still in die Konsole ging. Ein einziger + misslungener Versuch haette die Umstellung fuer immer als getan + vermerkt, und danach scheitert JEDE Liste an `m.gilt_ab`: 503 fuer + alle, mit einer Meldung, die nicht sagt, woran es liegt. + + Geprueft wird an einer Wegwerfdatei, nicht am laufenden Haus -- + eine Tabelle ohne die Spalten laesst sich sonst gar nicht + herstellen, ohne etwas kaputtzumachen. */ + const probe = new (await import("node:sqlite")).DatabaseSync(join(ordner, "probe-schema.db")); + probe.exec("CREATE TABLE material (id INTEGER PRIMARY KEY, dateiname TEXT)"); + + const NOETIG = ["gilt_ab", "gilt_bis"]; + const fehlt = () => { + const da = new Set(probe.prepare("PRAGMA table_info(material)").all().map((c) => c.name)); + return NOETIG.filter((n) => !da.has(n)); + }; + + ok(fehlt().length === 2, + `vor der Umstellung fehlen beide Spalten (${fehlt().join(", ")})`); + + probe.exec("ALTER TABLE material ADD COLUMN gilt_ab TEXT"); + ok(fehlt().length === 1 && fehlt()[0] === "gilt_bis", + `nach der halben Umstellung fehlt genau eine (${fehlt().join(", ")}) ` + + `-- genau dieser Fall haette "erledigt" heissen koennen`); + + probe.exec("ALTER TABLE material ADD COLUMN gilt_bis TEXT"); + ok(fehlt().length === 0, "nach der ganzen keine mehr"); + probe.close(); + + /* UND AM LAUFENDEN HAUS: Die Spalten sind wirklich da. Die Zeile + darueber beweist nur, dass die Rechnung stimmt -- nicht, dass sie + hier angewandt wurde. */ + const { DatabaseSync: DS } = await import("node:sqlite"); + const echt = new DS(process.env.WORKSPACE_DB); + const spalten = echt.prepare("PRAGMA table_info(material)").all().map((c) => c.name); + echt.close(); + ok(NOETIG.every((n) => spalten.includes(n)), + `und in der laufenden Ablage stehen sie auch (${spalten.length} Spalten: ` + + `${spalten.join(", ")})`); +} + melde(""); melde("=== 9b. Ein Fenster, das nicht geht ==="); { @@ -1033,11 +1079,11 @@ melde(""); /* Von 40 ueber 90 auf 145 angehoben (22.09.2026), als das Bearbeiten, das Zeitfenster und der Blick am echten Bildschirm dazukamen. Die Zahl ist keine Schaetzung: Sie steht knapp unter dem, was der Lauf - danach tatsaechlich gemeldet hat (155). Bei 90 waere der ganze + danach tatsaechlich gemeldet hat (159). Bei 90 waere der ganze Browserabschnitt still ausfallen koennen, ohne dass die Zahl etwas gesagt haette -- und genau das soll sie fangen. */ -if (geprueft < 145) { - console.log(` FEHL nur ${geprueft} Pruefungen gelaufen -- erwartet waren 145+`); +if (geprueft < 150) { + console.log(` FEHL nur ${geprueft} Pruefungen gelaufen -- erwartet waren 150+`); fehler++; } melde(fehler === 0 diff --git a/server/workspace-material.js b/server/workspace-material.js index d7fe4bea..db5380cf 100644 --- a/server/workspace-material.js +++ b/server/workspace-material.js @@ -127,14 +127,35 @@ function tabellen() { Fehler, ein neues CREATE wuerde die vorhandenen Zeilen nicht erreichen. Also nachsehen, was da ist, und nur ergaenzen, was fehlt -- dieselbe Bauart wie bei den Personen-Spalten. */ + const NOETIG = [["gilt_ab", "TEXT"], ["gilt_bis", "TEXT"]]; const da = new Set(d.prepare("PRAGMA table_info(material)").all().map((c) => c.name)); - for (const [spalte, form] of [["gilt_ab", "TEXT"], ["gilt_bis", "TEXT"]]) { + for (const [spalte, form] of NOETIG) { if (da.has(spalte)) continue; try { d.exec(`ALTER TABLE material ADD COLUMN ${spalte} ${form}`); console.log(`[material] Spalte '${spalte}' ergaenzt.`); } catch (f) { console.error(`[material] Spalte '${spalte}':`, f?.message); } } + + /* NACHSEHEN, OB ES AUCH GEKLAPPT HAT -- und das ist keine Formalie. + Im ersten Entwurf stand `bereit = true` UNBEDINGT hinter der + Schleife, und das `catch` darueber schluckte den Fehler. Ein + einziger misslungener Versuch (Datei gesperrt, Platte voll) haette + die Umstellung damit fuer immer als erledigt vermerkt. Danach + scheitert JEDE Liste an `SELECT ... m.gilt_ab` -- fuer alle, mit + einem 503 und der Meldung "gerade nicht verfuegbar", die nirgends + sagt, woran es liegt. + + Jetzt wird nachgezaehlt, der Vermerk nur bei Erfolg gesetzt (der + naechste Aufruf versucht es also wieder), und der Fehler + geworfen statt notiert: Ein Aufruf, der mit einer klaren Meldung + scheitert, ist besser als hundert, die raetseln. */ + const jetzt = new Set(d.prepare("PRAGMA table_info(material)").all().map((c) => c.name)); + const fehlend = NOETIG.map(([n]) => n).filter((n) => !jetzt.has(n)); + if (fehlend.length) { + throw new Error(`[material] Umstellung unvollstaendig, es fehlt: ${fehlend.join(", ")}` + + " -- die Liste kann ohne diese Spalten nicht gelesen werden."); + } bereit = true; }