# Umfang und Argumentformen der ISAM-Elemente (Aufgaben 1.1, 1.2) **Quelle.** `bas7advr.hlp` (BASIC 7 Advisor), Themenseiten unter https://dos-help.soulsphere.org/bas7advr.hlp/ (abgerufen 2026-09-04). Die Themenliste selbst ist bereits in `openspec/changes/archive/2026-09-04-phase-3-runtime-bildschirm/rohliste-original-hilfe.md` wortgetreu festgehalten; hier kommen die Syntaxzeilen der Einzelthemen dazu. ## 1.1 Umfangsabgleich Der ISAM-Abschnitt der Original-Hilfe führt genau diese Themen (Zeilen der Rohliste in Klammern): | Thema der Rohliste | Zeile | Elemente | |---|---|---| | `BEGINTRANS Statement` | 26 | `BEGINTRANS` | | `BOF Function` | 28 | `BOF` | | `COMMITTRANS Statement` | 47 | `COMMITTRANS` | | `CREATEINDEX Statement` | 51 | `CREATEINDEX` | | `DELETE Statement` | 64 | `DELETE` | | `DELETEINDEX Statement` | 65 | `DELETEINDEX` | | `DELETETABLE Statement` | 66 | `DELETETABLE` | | `GETINDEX$ Function` | 99 | `GETINDEX$` | | `INSERT Statement` | 110 | `INSERT` | | `MOVEFIRST, MOVELAST, MOVENEXT, MOVEPREVIOUS Statements` | 145 | 4 Elemente | | `RETRIEVE Statement` | 195 | `RETRIEVE` | | `ROLLBACK, ROLLBACK ALL Statements` | 200 | `ROLLBACK` | | `SAVEPOINT Function` | 206 | `SAVEPOINT` | | `SEEKGT, SEEKGE, SEEKEQ Statements` | 211 | 3 Elemente | | `SETINDEX Statement` | 213 | `SETINDEX` | | `SETMEM Function` | 214 | `SETMEM` | | `UPDATE Statement` | 259 | `UPDATE` | Das sind **22 Elemente**. `docs/inventar.md` führt in der Gruppe `ISAM` genau dieselben 22 Namen, alle mit Status `offen`. Der Umfang geht damit **nicht** über die Aufzählung im Proposal hinaus — die Liste im Proposal ist deckungsgleich. **Kein eigenes Element:** `TEXTCOMP` kommt in der Themenliste nicht vor (bestätigt den Befund aus `design.md`, D4). Ebenso wenig ein Thema für Sicherungspunkte außer `SAVEPOINT` oder für Datenbankwartung. **Elemente mit zusätzlichem ISAM-Verhalten**, die schon anderweitig implementiert sind und deshalb keinen eigenen Inventareintrag der Gruppe `ISAM` haben: `OPEN` (Klausel `FOR ISAM`), `CLOSE`, `EOF`, `LOF`, `LOC`. ## 1.2 Argumentformen je Element Syntaxzeilen wortgetreu aus der jeweiligen Themenseite der Original-Hilfe. | Element | Syntax (Original-Hilfe) | Themenseite | |---|---|---| | `OPEN … FOR ISAM` | `OPEN database$ FOR ISAM tabletype tablename$ AS [#]filenumber%` | `x_dot_opfior.html` | | `CREATEINDEX` | `CREATEINDEX [#]filenumber%,indexname$,unique%,columnname$[,columnname$]` | `x_dot_CREATEINDEXr.html` | | `DELETEINDEX` | `DELETEINDEX [#]filenumber%,indexname$` | `x_dot_DELETEINDEXr.html` | | `SETINDEX` | `SETINDEX [#]filenumber%[,indexname$]` | `x_dot_SETINDEXr.html` | | `GETINDEX$` | `GETINDEX$ (filenumber%)` | `x_dot_GETINDEX$r.html` | | `INSERT` | `INSERT [#]filenumber%,recordvariable` | `x_dot_INSERTr.html` | | `RETRIEVE` | `RETRIEVE [#]filenumber%,recordvariable` | `x_dot_RETRIEVEr.html` | | `UPDATE` | `UPDATE [#]filenumber%,recordvariable` | `x_dot_UPDATEr.html` | | `DELETE` | `DELETE [#]filenumber%` | `x_dot_DELETEr.html` | | `DELETETABLE` | `DELETETABLE database$,tablename$` | `x_dot_DELETETABLEr.html` | | `MOVEFIRST` u. a. | `MOVEFIRST [#]filenumber%` (ebenso `MOVELAST`, `MOVENEXT`, `MOVEPREVIOUS`) | `x_dot_MOVEFIRSTr.html` | | `SEEKGT`/`SEEKGE`/`SEEKEQ` | `SEEKGT [#]filenumber% ,keyvalue [,keyvalue]…` | `x_dot_seekisamr.html` | | `BEGINTRANS` | `BEGINTRANS` | `x_dot_BEGINTRANSr.html` | | `COMMITTRANS` | `COMMITTRANS` | `x_dot_COMMITTRANSr.html` | | `ROLLBACK` | `ROLLBACK [savepoint%]` bzw. `ROLLBACK ALL` | `x_dot_ROLLBACKr.html` | | `SAVEPOINT` | `SAVEPOINT` (Funktion, liefert eine ganze Zahl) | `x_dot_SAVEPOINTr.html` | | `SETMEM` | `SETMEM(numeric-expression&)` | `x_dot_setmemr.html` | | `BOF` | `BOF(filenumber%)` | `x_dot_BOFr.html` | ### Befund zur offenen Frage aus design.md Die Spaltenliste bei `CREATEINDEX` ist **keine** Zeichenkette mit Trennzeichen, sondern eine **Folge einzelner Stringargumente**: `columnname$[,columnname$]…`. Die Absenkung übernimmt diese Form unverändert; `CREATEINDEX` ist damit variadisch (4 bis 12 Argumente, also bis zu neun Indexspalten). ### Ergänzung über die Original-Hilfe hinaus: absteigende Spalten Die Original-Hilfe kennt bei `CREATEINDEX` **keine** Angabe der Sortierrichtung — Indizes sind dort immer aufsteigend. Die Anforderung „Indexverwaltung" dieses Changes verlangt aber auf- **und** absteigende Spalten. Gewählte Schreibweise: ein vorangestelltes `-` am Spaltennamen. ```basic CREATEINDEX #1, "NachPreis", 0, "Nachname", "-Preis" ``` Sie ist eindeutig und kollisionsfrei, weil ein Feldname einer `TYPE`-Anweisung nie mit `-` beginnen kann; Programme des Vorbilds bleiben dadurch unverändert gültig. Festgehalten in docs/sprachreferenz.md und docs/bibliothek.md. ### Cursor-Semantik folgt dem Vorbild Die Delta-Spezifikation schrieb ursprünglich an zwei Stellen eine andere Cursorlage vor, als die Original-Hilfe beschreibt. Entscheidung vom 2026-09-04: **bei Semantik und Syntax gewinnt das Vorbild, wo immer das möglich ist.** Die Spezifikation wurde daraufhin angeglichen, nicht die Umsetzung: | Situation | Original-Hilfe (und jetzt auch Terminal Basic) | |---|---| | nach `SETINDEX` | „the current record is the first record according to that index" — der erste Satz der neuen Ordnung ist der aktuelle | | nach `DELETE` | „the record following the deleted record becomes the current record"; war der gelöschte der letzte, steht der Cursor am Ende der Tabelle ohne aktuellen Satz | `SETINDEX` ohne Indexnamen bzw. mit `""` wählt den NULL-Index: „If you omit the `indexname$` argument or specify double quotes for it, the current index is the NULL index" — er „represents the order in which records were added to the file". ### Präfixsuche: Verhalten je Suchart Die Original-Hilfe unterscheidet die Sucharten bei zu wenigen Schlüsselwerten ausdrücklich; die Umsetzung übernimmt das: - `SEEKEQ` mit unvollständigem Schlüssel **schlägt immer fehl** („SEEKEQ with insufficient keyvalues always fails"). - `SEEKGE` sucht mit den vorhandenen Werten als Präfix. - `SEEKGT` mit unvollständigem Schlüssel positioniert auf dem **ersten passenden** Satz — also wie `SEEKGE`, nicht hinter der Präfixgruppe. ### Fehler 87: Auslöser ist die Suche über den NULL-Index Der Proposal-Abschnitt „ISAM-Fehlersemantik" nennt Code 87 („ISAM - Invalid operation on NULL index"). Die Themenseite zur `SEEK`-Familie schweigt zur Lage ohne aktiven Index — der Fehlerkatalog des Vorbilds benennt sie aber genau: der NULL-Index führt keine Schlüssel, sondern nur die Einfügereihenfolge, eine Schlüsselsuche über ihn ist deshalb die „unzulässige Operation auf dem NULL-Index". Die Delta-Spezifikation nannte hier zunächst Fehler 83; sie ist mit der Entscheidung vom 2026-09-04 („bei Semantik gewinnt das Vorbild") auf 87 angeglichen. **83** bleibt dem wirklich unbekannten Indexnamen vorbehalten und wird von `SETINDEX` und `DELETEINDEX` ausgelöst. Damit hat jeder Code von 81 bis 89 einen Auslöser. Bewegung über den NULL-Index bleibt zulässig (`MOVE`-Familie in Einfügereihenfolge) — die Original-Hilfe beschreibt den NULL-Index ausdrücklich als Reihenfolge, nicht als Fehlerzustand. ## Befunde der Verifikation (2026-09-04) Vier Befunde aus `/opsx:verify`, alle umgesetzt. ### `CLOSE` beendet keine Transaktion Ursprünglich schrieb `CLOSE` eine laufende Transaktion fest, um Aufgabe 4.5 („schreibt ausstehende Änderungen fest") zu erfüllen. Das war zu weit gegriffen und hatte zwei beobachtbare Folgen: ```basic BEGINTRANS : INSERT #1, p : CLOSE #1 ' Satz blieb erhalten BEGINTRANS : INSERT #1, p : END ' Satz verfiel ``` und, schlimmer, über Dateinummern hinweg: ```basic OPEN … AS #1 : OPEN … AS #2 BEGINTRANS : INSERT #1, p : CLOSE #2 ' schrieb die Änderung an #1 fest ROLLBACK ALL ' → Fehler 5, Satz überlebte ``` Aufgabe 4.5 ist auch ohne diese Festschreibung erfüllt, weil jede Operation außerhalb einer Transaktion für sich eine Transaktion ist. `CLOSE` löst seither nur die Bindung; über das Ende einer Transaktion entscheiden allein `COMMITTRANS` und `ROLLBACK ALL`, und eine beim Programmende offene Transaktion verfällt — in beiden Wegen gleich. Delta-Spec, Aufgabe 4.5 und die Referenzen sind angeglichen; zwei Einheitentests halten es fest. ### `CREATEINDEX` ohne Obergrenze der Spaltenzahl Die Signatur begrenzte den Index auf neun Spalten. Die Original-Hilfe nennt keine Obergrenze, also darf die Signatur auch keine setzen: die Spaltenargumente werden jetzt wie bei `INSTR` gesondert geprüft (ab dem vierten Argument je ein String), die Argumentzahl ist offen. ### Kein Index-Torso nach Fehler 86 Scheiterte `CREATEINDEX` an der Eindeutigkeit, blieb innerhalb einer Transaktion eine halb gefüllte Indextabelle zurück, die keine Indexdefinition mehr nannte. `index_anlegen` bildet jetzt erst alle Schlüssel und prüft die Eindeutigkeit, bevor es schreibt — dieselbe Reihenfolge wie in `satz_schreiben`. ### Toter Klon in `RETRIEVE` `satz_lesen` klonte das Tabellenlayout je Aufruf, ohne es zu benutzen. Entfernt.