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>
11 KiB
isam-datenbank Specification
Purpose
Die ISAM-Unterstützung bietet indizierten Satzzugriff auf Tabellen einer Datenbankdatei: Sätze werden über benannte Indizes geordnet durchlaufen und über Schlüsselvergleiche gesucht, Änderungen laufen in Transaktionen und Verstöße melden die ISAM-Fehlercodes des Vorbilds.
Requirements
Requirement: Datenbank- und Tabellenbindung an eine Dateinummer
OPEN datenbank$ FOR ISAM typname tabellenname AS #n SHALL eine Tabelle
einer Datenbankdatei an eine Dateinummer binden. Das Satzlayout SHALL
sich aus dem benannten benutzerdefinierten Typ ergeben; dessen Felder
sind die Spalten der Tabelle. Existiert die Tabelle noch nicht, SHALL sie
mit diesem Layout angelegt werden; existiert sie mit abweichendem Layout,
MUST Laufzeitfehler 88 „ISAM - Database inconsistent" auftreten. Ein
ungültiger Tabellen- oder Datenbankname MUST Fehler 81 „ISAM - Invalid
name" auslösen. CLOSE SHALL die Bindung lösen; ausstehende Änderungen
sind dabei bereits festgeschrieben, weil jede Operation außerhalb einer
Transaktion für sich eine Transaktion ist. Eine laufende Transaktion MUST
CLOSE unberührt lassen — über ihr Ende entscheiden allein COMMITTRANS
und ROLLBACK ALL. DELETETABLE SHALL eine Tabelle samt ihren
Indizes entfernen; eine nicht vorhandene Tabelle MUST Fehler 82 „ISAM -
Table not found" auslösen.
Scenario: Tabelle wird beim ersten Öffnen angelegt
- WHEN eine Datenbank ohne die Tabelle
KundenmitOPEN "db" FOR ISAM KundeTyp "Kunden" AS #1geöffnet wird - THEN entsteht die Tabelle mit den Feldern des Typs und die Dateinummer ist nutzbar
Scenario: Abweichendes Satzlayout
- WHEN eine bestehende Tabelle mit einem Typ geöffnet wird, dessen Felder nicht zu ihren Spalten passen
- THEN tritt Laufzeitfehler 88 auf
Scenario: CLOSE lässt eine laufende Transaktion stehen
- WHEN innerhalb einer Transaktion eine andere Dateinummer mit
CLOSEgeschlossen wird - THEN läuft die Transaktion weiter und ein folgendes
ROLLBACK ALLnimmt ihre Änderungen zurück
Scenario: Entfernte Tabelle
- WHEN
DELETETABLEfür eine nicht vorhandene Tabelle aufgerufen wird - THEN tritt Laufzeitfehler 82 auf
Requirement: Indexverwaltung
CREATEINDEX SHALL einen benannten Index über eine oder mehrere Spalten
anlegen, wahlweise eindeutig oder mehrdeutig und je Spalte auf- oder
absteigend geordnet. DELETEINDEX SHALL einen Index entfernen.
SETINDEX SHALL den aktiven Index einer Dateinummer setzen und damit die
Reihenfolge bestimmen, in der Sätze durchlaufen werden; GETINDEX$ SHALL
den Namen des aktiven Index liefern. SETINDEX ohne Indexnamen (oder mit
leerem Namen) SHALL den NULL-Index wählen, also die Einfügereihenfolge;
GETINDEX$ liefert dafür einen leeren String. Ein unbekannter Indexname
MUST Laufzeitfehler 83 „ISAM - Index not found" auslösen, ein unbekannter
Spaltenname Fehler 84 „ISAM - Invalid column". Nach SETINDEX SHALL der
erste Satz in der Ordnung des gewählten Index der aktuelle Satz sein; ist
die Tabelle leer, gibt es keinen aktuellen Satz.
Scenario: Aktiver Index bestimmt die Reihenfolge
- WHEN ein Index über die Spalte
Namegesetzt ist und die Sätze mitMOVEFIRSTundMOVENEXTdurchlaufen werden - THEN erscheinen sie in aufsteigender Reihenfolge der Spalte
Name
Scenario: Unbekannter Index
- WHEN
SETINDEX #1, "GibtsNicht"ausgeführt wird - THEN tritt Laufzeitfehler 83 auf
Scenario: Aktueller Satz nach SETINDEX
- WHEN ein Index gesetzt wird, dessen Ordnung mit einem anderen Satz beginnt als die bisherige
- THEN ist dieser Satz ohne weitere Bewegung der aktuelle Satz
Scenario: Index über unbekannte Spalte
- WHEN
CREATEINDEXeine Spalte nennt, die der Satztyp nicht führt - THEN tritt Laufzeitfehler 84 auf
Requirement: Cursorbewegung in der Ordnung des aktiven Index
MOVEFIRST, MOVELAST, MOVENEXT und MOVEPREVIOUS SHALL den Cursor
in der Ordnung des aktiven Index bewegen. Läuft der Cursor über das Ende
hinaus, SHALL EOF für diese Dateinummer wahr werden; läuft er über den
Anfang hinaus, SHALL BOF wahr werden. In beiden Fällen SHALL der Cursor
als unpositioniert gelten. Eine Bewegung ohne aktiven Index SHALL der
Einfügereihenfolge folgen.
Scenario: Cursor läuft über das Ende hinaus
- WHEN nach dem letzten Satz
MOVENEXTausgeführt wird - THEN liefert
EOFfür diese Dateinummer wahr
Scenario: Rückwärts über den Anfang hinaus
- WHEN auf dem ersten Satz
MOVEPREVIOUSausgeführt wird - THEN liefert
BOFfür diese Dateinummer wahr
Requirement: Schlüsselsuche
SEEKEQ, SEEKGT und SEEKGE SHALL den Cursor auf den ersten Satz
setzen, dessen Schlüssel im aktiven Index gleich, größer bzw.
größer-gleich dem angegebenen Wert ist. Die Zahl der Schlüsselwerte MUST
höchstens der Spaltenzahl des aktiven Index entsprechen; ein
mehrspaltiger Index SHALL mit einem Präfix der Spalten durchsucht werden
können. Findet die Suche keinen Satz, SHALL EOF wahr werden und der
Cursor unpositioniert bleiben. Eine Suche über den NULL-Index MUST
Laufzeitfehler 87 „ISAM - Invalid operation on NULL index" auslösen — er
führt keine Schlüssel, sondern nur die Einfügereihenfolge.
Scenario: Suche nach größerem Schlüssel
- WHEN Sätze mit den Schlüsseln 10, 20 und 30 vorliegen und
SEEKGT #1, 20ausgeführt wird - THEN steht der Cursor auf dem Satz mit Schlüssel 30
Scenario: Erfolglose Suche
- WHEN
SEEKGT #1, 30bei größtem Schlüssel 30 ausgeführt wird - THEN liefert
EOFwahr
Scenario: Suche über Präfix eines mehrspaltigen Index
- WHEN der aktive Index über
NachnameundVornamegeht und mit nur einem Wert gesucht wird - THEN positioniert die Suche auf dem ersten Satz mit passendem
Nachname
Requirement: Satzoperationen auf dem aktuellen Satz
INSERT SHALL einen Satz aus einer Variablen des Tabellentyps einfügen,
RETRIEVE den aktuellen Satz in eine solche Variable lesen, UPDATE ihn
aus einer solchen Variablen überschreiben und DELETE ihn entfernen.
RETRIEVE, UPDATE und DELETE ohne positionierten Cursor MUST
Laufzeitfehler 85 „ISAM - No current record" auslösen. Ein INSERT oder
UPDATE, das einen als eindeutig angelegten Index verletzen würde, MUST
Laufzeitfehler 86 „ISAM - Duplicate value for unique index" auslösen und
den Satzbestand unverändert lassen. Nach DELETE SHALL der auf den
gelöschten folgende Satz der aktuelle sein; war der gelöschte der letzte
in der Ordnung des aktiven Index, SHALL der Cursor am Ende der Tabelle
stehen und es SHALL keinen aktuellen Satz geben. Alle Indizes der Tabelle
SHALL nach jeder Satzoperation die neue Ordnung widerspiegeln.
Scenario: Einfügen und Zurücklesen
- WHEN ein Satz eingefügt, per
SEEKEQgesucht und mitRETRIEVEgelesen wird - THEN stimmen alle Feldwerte mit den eingefügten überein
Scenario: Operation ohne aktuellen Satz
- WHEN hinter dem letzten Satz — also nach
MOVENEXTam Ende —RETRIEVE #1, kausgeführt wird - THEN tritt Laufzeitfehler 85 auf
Scenario: Aktueller Satz nach DELETE
- WHEN ein Satz gelöscht wird, auf den in der Ordnung des aktiven Index ein weiterer folgt
- THEN ist dieser folgende Satz der aktuelle
Scenario: Verstoß gegen eindeutigen Index
- WHEN ein Satz eingefügt wird, dessen Schlüssel in einem eindeutigen Index bereits vorkommt
- THEN tritt Laufzeitfehler 86 auf und der Satzbestand bleibt unverändert
Scenario: Index folgt der Änderung
- WHEN die indizierte Spalte eines Satzes per
UPDATEgeändert wird - THEN erscheint der Satz beim nächsten Durchlauf an seiner neuen Position in der Indexordnung
Requirement: Transaktionen mit Rücknahme
BEGINTRANS SHALL eine Transaktion eröffnen, COMMITTRANS alle
Änderungen seit ihrem Beginn festschreiben und ROLLBACK sie
zurücknehmen. SAVEPOINT SHALL als Funktion einen Sicherungspunkt
setzen und dessen Kennung liefern; ROLLBACK mit einer solchen Kennung
SHALL auf diesen Punkt zurücksetzen, ohne die Transaktion aufzugeben.
ROLLBACK ALL SHALL alle Änderungen seit BEGINTRANS zurücknehmen und
die Transaktion beenden. Nach jeder Rücknahme MUST der Satzbestand
einschließlich aller Indizes dem Zustand zum Bezugspunkt entsprechen und
der Cursor als unpositioniert gelten. Eine beim Programmende nicht
festgeschriebene Transaktion MUST wirkungslos bleiben.
Scenario: Rücknahme stellt den Bestand wieder her
- WHEN nach
BEGINTRANSSätze eingefügt und gelöscht werden und dannROLLBACKfolgt - THEN entspricht der Bestand beim erneuten Durchlauf dem Zustand vor
BEGINTRANS
Scenario: Rücknahme auf einen Sicherungspunkt
- WHEN innerhalb einer Transaktion
s = SAVEPOINTausgewertet, danach geändert und mitROLLBACK szurückgesetzt wird - THEN bleiben die Änderungen vor dem Sicherungspunkt erhalten und die danach sind zurückgenommen
Scenario: ROLLBACK ALL beendet die Transaktion
- WHEN nach mehreren Sicherungspunkten
ROLLBACK ALLausgeführt wird - THEN entspricht der Bestand dem Zustand vor
BEGINTRANSund die Transaktion ist beendet
Requirement: Vergleichsreihenfolge für Indizes
Textspalten SHALL in Indizes nach einer festgelegten, dokumentierten Sortierordnung geordnet werden. Diese Ordnung MUST dieselbe sein, die der Vergleichsoperator des Dialekts auf Strings anwendet, damit ein Programm die Satzreihenfolge vorhersagen kann. Die gewählte Ordnung MUST in docs/sprachreferenz.md festgehalten sein, einschließlich der Behandlung von Groß- und Kleinschreibung und von Zeichen jenseits von ASCII.
Scenario: Indexordnung entspricht dem Stringvergleich
- WHEN zwei Texte als Schlüssel indiziert und dieselben Werte mit
<verglichen werden - THEN entspricht ihre Reihenfolge im Index dem Ergebnis des Vergleichs
Requirement: Pufferverwaltung mit benanntem Fehler
SETMEM SHALL als Funktion die für ISAM verfügbare Puffergröße um
den übergebenen Betrag ändern und die danach verfügbare Größe liefern.
Reicht
der verfügbare Puffer für eine Operation nicht aus, MUST Laufzeitfehler 89
„ISAM - Insufficient ISAM buffers" auftreten statt eines generischen
Fehlers oder eines stillen Abbruchs. Weicht die Bedeutung von SETMEM
mangels DOS-Speichermodell vom Vorbild ab, MUST die Abweichung in
docs/sprachreferenz.md dokumentiert sein.
Scenario: Pufferfehler wird benannt
- WHEN eine Operation den verfügbaren ISAM-Puffer überschreitet
- THEN tritt Laufzeitfehler 89 auf
Requirement: Eigenes Datenbankdateiformat
Die Datenbankdatei SHALL ein eigenes, in docs/dateiformate.md beschriebenes Format verwenden und ist bewusst nicht binärkompatibel zu Datenbankdateien des Vorbilds — dieselbe Linie wie bei den UTF-32-Festtextfeldern. Das Format SHALL eine Formatversion tragen; eine unbekannte Version MUST mit einem benannten Fehler abgewiesen werden statt fehlinterpretiert zu werden. Eine strukturell beschädigte Datei MUST Laufzeitfehler 88 auslösen.
Scenario: Unbekannte Formatversion
- WHEN eine Datenbankdatei mit einer höheren Formatversion geöffnet wird
- THEN wird sie mit einem benannten Fehler abgewiesen und nicht gelesen
Scenario: Beschädigte Datei
- WHEN eine strukturell beschädigte Datenbankdatei geöffnet wird
- THEN tritt Laufzeitfehler 88 auf