OpenSpec: phase-3-isam archiviert, Delta-Specs gesynct
Neue Capability isam-datenbank mit 9 Anforderungen und 25 Szenarien: Tabellenbindung an eine Dateinummer, Indexverwaltung, Cursorbewegung, Schluesselsuche, Satzoperationen, Transaktionen mit Ruecknahme, Vergleichsreihenfolge, Pufferverwaltung und das eigene Dateiformat. sprach-frontend um eine Anforderung erweitert: ISAM-Anweisungen und -Funktionen in Grammatik und Signaturpruefung. Die Delta-Spec wurde vor dem Archivieren an die Original-Hilfe angeglichen -- Cursorlage nach SETINDEX und DELETE, Fehlercode der Suche ueber den NULL-Index. Die Change-Notiz umfang-und-signaturen.md haelt Umfangsabgleich, Argumentformen mit Quellenangabe je Themenseite und die Verifikationsbefunde fest. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user