ISAM-Datenbankunterstuetzung
Setzt den OpenSpec-Change phase-3-isam um (49/49 Aufgaben) und schliesst damit Phase 3 ab. Alle 22 ISAM-Elemente des Inventars sind implementiert; der Abdeckungsstand steigt auf 217 implementiert / 15 offen / 53 Non-Feature. Frontend - ISAM-Anweisungen als eigener Zweig im Parser: NAME [#]n [, arg ...], Sonderform ROLLBACK ALL ueber eine Sentinel-Kennung - 22 Signaturen in builtin_stmt/builtin_fn, neue Argumentart R (Satzvariable eines benutzerdefinierten Typs) - Satzargumente von INSERT/RETRIEVE/UPDATE werden gegen den Typ der Dateinummer geprueft, sofern beide literal bekannt sind - Die Unsupported-Absenkung von OPEN ... FOR ISAM entfaellt Speicherschicht (tb-runtime::isam, einziger Ort mit redb) - Je Tabelle eine Satztabelle satz-id -> Satzbytes, je Index eine Tabelle Schluesselbytes -> satz-id. Satz-IDs sind monoton und werden nie wiederverwendet: der Cursor merkt sich eine ID, eine neu vergebene koennte still auf einen fremden Satz zeigen - Satzbytes entstehen mit fileio::wert_schreiben/wert_lesen, also mit den Recordpuffern und der UTF-32-Festtextkodierung aus datei-eio - Ordnungserhaltende Schluesselkodierung je Spaltentyp; Text als UTF-8, dessen Bytereihenfolge die Codepoint-Reihenfolge ist und damit dieselbe Ordnung wie CmpStr der VM. Ein Eigenschaftstest ueber 5000 zufaellige Wertepaare je Typ haelt fest, dass der Bytevergleich dem fachlichen Vergleich entspricht -- eine Ordnungsverletzung faellt sonst erst bei bestimmten Datenwerten auf - Cursor als Wert (aktiver Index, letzte Satz-ID, unpositioniert), nicht als gehaltener Iterator: er ueberlebt Satzaenderungen und Transaktionsgrenzen - Sicherungspunkte ueber ein eigenes Ruecknahmeprotokoll; ROLLBACK ALL bricht die Bibliothekstransaktion direkt ab Semantik durchweg aus der Original-Hilfe - Die Argumentformen stammen erstmals aus den Einzelseiten, nicht nur aus der Themenliste. Das korrigierte eine Annahme des Entwurfs: die Spaltenliste von CREATEINDEX ist keine Zeichenkette mit Trennzeichen, sondern eine Folge einzelner Stringargumente - SEEKEQ mit unvollstaendigem Schluessel schlaegt immer fehl, SEEKGT mit Teilschluessel positioniert wie SEEKGE - Nach SETINDEX ist der erste Satz der neuen Ordnung aktuell, nach DELETE der folgende - Suche ueber den NULL-Index meldet 87, nicht 83; damit hat jeder Code von 81 bis 89 einen Ausloeser - Einzige Erweiterung: ein - vor dem Spaltennamen ordnet absteigend. Die Original-Hilfe kennt bei CREATEINDEX keine Sortierrichtung, die Anforderung verlangt sie. Kollisionsfrei, weil ein TYPE-Feldname nie mit - beginnen kann CLOSE beendet keine Transaktion - Erst schrieb es sie fest, womit das Schliessen irgendeiner Dateinummer die Transaktion aller anderen mit beendete und ein folgendes ROLLBACK ALL ins Leere lief. Ausstehende Aenderungen sind ohnehin festgeschrieben, weil jede Operation ausserhalb einer Transaktion fuer sich eine ist - Ueber das Ende entscheiden allein COMMITTRANS und ROLLBACK ALL; eine beim Programmende offene Transaktion verfaellt, in beiden Wegen gleich SETMEM und Fehler 89 - Ohne DOS-Speichermodell ist SETMEM die Obergrenze des ISAM-Puffers (Vorgabe 65536 Bytes); ohne echte Grenze waere Code 89 nie erreichbar und die Anweisung eine Attrappe Tests - 18 Einheitentests (Kodierung, Formatversion, Satz-IDs, Roundtrip ueber alle Feldtypen, Indexordnung, Cursor, Protokoll) - 6 Korpusprogramme: Tabellen, Indizes, Cursor, Saetze, Transaktionen, Puffer und Vergleichsordnung -- je in einem temporaeren Arbeits- verzeichnis, der Projektbaum bleibt sauber - Der VM-Test zu Fehler 73 prueft ISAM nicht mehr, sondern SETUEVENT; dafuer belegt ein neuer Test, dass OPEN ... FOR ISAM arbeitet Dokumentation: Datenbankdateiformat in dateiformate.md, Abschnitt 10a samt Sortierordnung und SETMEM-Abweichung in sprachreferenz.md, ISAM-Abschnitt in bibliothek.md, Inventar auf implementiert, PLAN.md schaerft die Leitplanke Referenzverhalten -- sie gilt auch gegenueber den eigenen Spezifikationen. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -174,6 +174,75 @@ solange Werte übrig sind. Eine Zeichenkette ohne Feld bei vorhandenen
|
||||
Werten löst Fehler 5 aus. `SetFormatCC` setzt das Währungszeichen
|
||||
über einen Ländercode; nicht aufgeführte Codes behalten `$`.
|
||||
|
||||
## ISAM
|
||||
|
||||
| Element | Art |
|
||||
|---|---|
|
||||
| `BEGINTRANS` | Anweisung |
|
||||
| `BOF` | Funktion |
|
||||
| `COMMITTRANS` | Anweisung |
|
||||
| `CREATEINDEX` | Anweisung |
|
||||
| `DELETE` | Anweisung |
|
||||
| `DELETEINDEX` | Anweisung |
|
||||
| `DELETETABLE` | Anweisung |
|
||||
| `GETINDEX$` | Funktion |
|
||||
| `INSERT` | Anweisung |
|
||||
| `MOVEFIRST` | Anweisung |
|
||||
| `MOVELAST` | Anweisung |
|
||||
| `MOVENEXT` | Anweisung |
|
||||
| `MOVEPREVIOUS` | Anweisung |
|
||||
| `RETRIEVE` | Anweisung |
|
||||
| `ROLLBACK` | Anweisung |
|
||||
| `SAVEPOINT` | Funktion |
|
||||
| `SEEKEQ` | Anweisung |
|
||||
| `SEEKGE` | Anweisung |
|
||||
| `SEEKGT` | Anweisung |
|
||||
| `SETINDEX` | Anweisung |
|
||||
| `SETMEM` | Funktion |
|
||||
| `UPDATE` | Anweisung |
|
||||
|
||||
Indizierter Satzzugriff auf Tabellen einer Datenbankdatei; die
|
||||
Dateinummer kommt aus `OPEN datenbank$ FOR ISAM typname tabelle$ AS #n`.
|
||||
Bei allen Anweisungen ist das `#` vor der Dateinummer optional.
|
||||
|
||||
`CREATEINDEX #n, name$, eindeutig%, spalte$[, spalte$]…` legt einen Index
|
||||
über bis zu neun Spalten an; `eindeutig%` ungleich 0 verbietet doppelte
|
||||
Schlüssel (Verstoß: Fehler 86, Satzbestand bleibt unverändert). Ein `-`
|
||||
vor dem Spaltennamen ordnet absteigend — eine Erweiterung über die
|
||||
Original-Hilfe hinaus. `SETINDEX #n` ohne Namen (oder mit `""`) wählt den
|
||||
NULL-Index (Einfügereihenfolge), `GETINDEX$` liefert dafür einen leeren
|
||||
String. Nach `SETINDEX` ist der erste Satz der neuen Ordnung der aktuelle.
|
||||
Unbekannter Index: Fehler 83, unbekannte Spalte: Fehler 84.
|
||||
|
||||
`INSERT`, `RETRIEVE` und `UPDATE` erwarten als zweites Argument eine
|
||||
Variable des Tabellentyps, `DELETE` nur die Dateinummer. Ohne
|
||||
positionierten Cursor melden `RETRIEVE`, `UPDATE` und `DELETE` Fehler 85.
|
||||
Nach `DELETE` wird der folgende Satz der aktuelle; war der gelöschte der
|
||||
letzte, steht der Cursor am Ende der Tabelle ohne aktuellen Satz. Alle
|
||||
Indizes werden nach jeder Satzoperation nachgeführt.
|
||||
|
||||
Die `MOVE`-Familie bewegt in der Ordnung des aktiven Index, ohne aktiven
|
||||
Index in Einfügereihenfolge. Läuft der Cursor über das Ende hinaus, wird
|
||||
`EOF(n)` wahr, über den Anfang hinaus `BOF(n)`; in beiden Fällen ist der
|
||||
Cursor danach unpositioniert. Die `SEEK`-Familie sucht im aktiven Index
|
||||
(über den NULL-Index: Fehler 87); eine erfolglose Suche setzt `EOF`. Ein
|
||||
mehrspaltiger Index lässt sich mit einem Präfix seiner Spalten
|
||||
durchsuchen, wobei `SEEKEQ` mit unvollständigem Schlüssel immer fehlschlägt.
|
||||
|
||||
`BEGINTRANS` eröffnet eine Transaktion, `COMMITTRANS` schreibt sie fest.
|
||||
`CLOSE` beendet sie nicht; eine beim Programmende offene Transaktion
|
||||
bleibt wirkungslos.
|
||||
`SAVEPOINT` liefert die Kennung eines Sicherungspunkts; `ROLLBACK kennung`
|
||||
setzt auf ihn zurück und lässt die Transaktion offen, `ROLLBACK` ohne
|
||||
Argument auf den letzten Sicherungspunkt bzw. den Transaktionsbeginn.
|
||||
`ROLLBACK ALL` nimmt alles seit `BEGINTRANS` zurück und beendet die
|
||||
Transaktion. Nach jeder Rücknahme ist der Cursor unpositioniert.
|
||||
|
||||
`SETMEM(n&)` verändert die ISAM-Puffergrenze um `n` Bytes und liefert die
|
||||
danach verfügbare Größe (Vorgabe 65536); ein Überschreiten meldet Fehler
|
||||
89. Bedeutung und Abweichung vom DOS-Speichermodell des Vorbilds stehen
|
||||
in der Sprachreferenz.
|
||||
|
||||
## Klang
|
||||
|
||||
| Element | Art |
|
||||
|
||||
@@ -69,6 +69,69 @@ Feste Strings (`STRING * n`) in Records werden als **UTF-32LE** gespeichert
|
||||
des Vorbilds; numerische Felder behalten ihr klassisches Layout
|
||||
(INTEGER i16, LONG i32, SINGLE f32, DOUBLE f64, CURRENCY i64, little-endian).
|
||||
|
||||
## ISAM-Datenbank (`OPEN … FOR ISAM`)
|
||||
|
||||
Eigenes Format, **bewusst nicht binärkompatibel** zu Datenbankdateien des
|
||||
Vorbilds — dieselbe Linie wie bei den UTF-32-Records oben. Ein
|
||||
Konvertierungswerkzeug ist Nicht-Ziel; das Vorbildformat wird weder
|
||||
gelesen noch geschrieben.
|
||||
|
||||
**Träger.** Die Datei ist eine [`redb`](https://crates.io/crates/redb)-Datei
|
||||
(eingebetteter transaktionaler B-Baum). `redb` liefert Seitenverwaltung,
|
||||
Transaktionen und Crash-Sicherheit; die ISAM-Semantik darüber ist eigener
|
||||
Code (siehe `tb-runtime::isam`).
|
||||
|
||||
**Formatversion.** Die Datei trägt in ihrer Metatabelle unter `version`
|
||||
eine 32-Bit-Formatversion (little-endian), derzeit **1**. Eine Datei mit
|
||||
höherer Version wird beim Öffnen mit Laufzeitfehler 88 („ISAM - Database
|
||||
inconsistent") abgewiesen, statt fehlinterpretiert zu werden. Ebenso
|
||||
abgewiesen wird eine bestehende Datei ohne Versionsmarke sowie jede
|
||||
strukturell unlesbare Datei.
|
||||
|
||||
**Tabellen in der Datei.** Je Datenbankdatei:
|
||||
|
||||
| `redb`-Tabelle | Schlüssel → Wert | Inhalt |
|
||||
|---|---|---|
|
||||
| `tb_meta` | `&str → Bytes` | Formatversion, Layout, Indexdefinitionen, ID-Zähler |
|
||||
| `satz/<tabelle>` | `u64 → Bytes` | ein Satz je Eintrag, Schlüssel ist die Satz-ID |
|
||||
| `idx/<tabelle>/<index>` | `Bytes → u64` | Indexeintrag: Schlüsselbytes → Satz-ID |
|
||||
|
||||
Die Einträge in `tb_meta` je Tabelle `T`:
|
||||
|
||||
- `tab:T` — Layoutkurzform `spalte:typ;…` mit den Typkürzeln `I2`, `I4`,
|
||||
`R4`, `R8`, `CY`, `T<n>` (fester Text mit `n` Zeichen). Beim Öffnen einer
|
||||
bestehenden Tabelle wird sie gegen den angegebenen Satztyp geprüft;
|
||||
Abweichung ist Fehler 88.
|
||||
- `idx:T` — eine Zeile je Index, `name<TAB>eindeutig<TAB>spalten`, Spalten
|
||||
als Feldnummern mit `-` für absteigend.
|
||||
- `seq:T` — nächste Satz-ID (u64, little-endian). IDs werden **monoton**
|
||||
vergeben und **nie wiederverwendet**: ein Cursor merkt sich eine Satz-ID,
|
||||
und eine nach `DELETE` neu vergebene ID ließe ihn still auf einen fremden
|
||||
Satz zeigen.
|
||||
|
||||
**Satzbytes.** Ein Satz liegt genau so im Speicher wie ein Record bei
|
||||
`PUT` auf eine `RANDOM`-Datei: numerische Felder klassisch und
|
||||
little-endian, feste Strings als UTF-32LE. Daher gilt die Inkompatibilität
|
||||
zum Vorbild aus demselben Grund wie oben.
|
||||
|
||||
**Indexschlüssel.** Die Schlüsselbytes sind **ordnungserhaltend** kodiert —
|
||||
ihr Byte-Vergleich entspricht dem fachlichen Vergleich, weil `redb` nach
|
||||
Bytes ordnet:
|
||||
|
||||
- Ganzzahlen: Big-Endian fester Breite mit gekipptem Vorzeichenbit.
|
||||
- Gleitkommazahlen: Big-Endian der Bitdarstellung; bei negativem
|
||||
Vorzeichen alle Bits invertiert, sonst das oberste Bit gesetzt.
|
||||
- Text: UTF-8 (dessen Bytereihenfolge ist die Codepoint-Reihenfolge, siehe
|
||||
„Sortierordnung" der Sprachreferenz). `00` im Text wird zu `00 FF`
|
||||
verdoppelt, den Abschluss bildet `00 00` — damit ordnet ein echtes
|
||||
Präfix vor jedem längeren Text.
|
||||
- Absteigende Spalten: alle Bytes dieser Spalte invertiert.
|
||||
- Mehrspaltig: Verkettung in Spaltenreihenfolge.
|
||||
|
||||
An jeden Indexschlüssel sind acht Bytes Satz-ID (Big-Endian) angehängt.
|
||||
Das macht auch Einträge eines mehrdeutigen Index eindeutig, hält Dubletten
|
||||
in Einfügereihenfolge und macht die Präfixsuche zur Bereichsabfrage.
|
||||
|
||||
## Kompilat: `.tbc` (neu, eigenes Format)
|
||||
|
||||
Container für TBVM-Bytecode, Entwurf in [tbvm-design.md](tbvm-design.md).
|
||||
|
||||
@@ -21,7 +21,7 @@ namentlich abgewiesen. `Non-Feature` = abgelehnt, gelistet unter
|
||||
**Fundstelle.** Bei `implementiert` das Modul, bei `Non-Feature` der
|
||||
Abschnitt der Sprachreferenz, bei `offen` ein Strich.
|
||||
|
||||
**Abdeckung.** implementiert 195 · offen 37 · Non-Feature 53 · gesamt 285
|
||||
**Abdeckung.** implementiert 217 · offen 15 · Non-Feature 53 · gesamt 285
|
||||
|
||||
| Name | Art | Gruppe | Status | Fundstelle | Quelle |
|
||||
|---|---|---|---|---|---|
|
||||
@@ -199,28 +199,28 @@ Abschnitt der Sprachreferenz, bei `offen` ein Strich.
|
||||
| `VARPTR$` | Funktion | Hardware | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
|
||||
| `VARSEG` | Funktion | Hardware | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
|
||||
| `WAIT` | Anweisung | Hardware | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
|
||||
| `BEGINTRANS` | Anweisung | ISAM | offen | - | bas7advr |
|
||||
| `BOF` | Funktion | ISAM | offen | - | bas7advr |
|
||||
| `COMMITTRANS` | Anweisung | ISAM | offen | - | bas7advr |
|
||||
| `CREATEINDEX` | Anweisung | ISAM | offen | - | bas7advr |
|
||||
| `DELETE` | Anweisung | ISAM | offen | - | bas7advr |
|
||||
| `DELETEINDEX` | Anweisung | ISAM | offen | - | bas7advr |
|
||||
| `DELETETABLE` | Anweisung | ISAM | offen | - | bas7advr |
|
||||
| `GETINDEX$` | Funktion | ISAM | offen | - | bas7advr |
|
||||
| `INSERT` | Anweisung | ISAM | offen | - | bas7advr |
|
||||
| `MOVEFIRST` | Anweisung | ISAM | offen | - | bas7advr |
|
||||
| `MOVELAST` | Anweisung | ISAM | offen | - | bas7advr |
|
||||
| `MOVENEXT` | Anweisung | ISAM | offen | - | bas7advr |
|
||||
| `MOVEPREVIOUS` | Anweisung | ISAM | offen | - | bas7advr |
|
||||
| `RETRIEVE` | Anweisung | ISAM | offen | - | bas7advr |
|
||||
| `ROLLBACK` | Anweisung | ISAM | offen | - | bas7advr |
|
||||
| `SAVEPOINT` | Funktion | ISAM | offen | - | bas7advr |
|
||||
| `SEEKEQ` | Anweisung | ISAM | offen | - | bas7advr |
|
||||
| `SEEKGE` | Anweisung | ISAM | offen | - | bas7advr |
|
||||
| `SEEKGT` | Anweisung | ISAM | offen | - | bas7advr |
|
||||
| `SETINDEX` | Anweisung | ISAM | offen | - | bas7advr |
|
||||
| `SETMEM` | Funktion | ISAM | offen | - | bas7advr |
|
||||
| `UPDATE` | Anweisung | ISAM | offen | - | bas7advr |
|
||||
| `BEGINTRANS` | Anweisung | ISAM | implementiert | tb-runtime::isam | bas7advr |
|
||||
| `BOF` | Funktion | ISAM | implementiert | tb-runtime::isam | bas7advr |
|
||||
| `COMMITTRANS` | Anweisung | ISAM | implementiert | tb-runtime::isam | bas7advr |
|
||||
| `CREATEINDEX` | Anweisung | ISAM | implementiert | tb-runtime::isam | bas7advr |
|
||||
| `DELETE` | Anweisung | ISAM | implementiert | tb-runtime::isam | bas7advr |
|
||||
| `DELETEINDEX` | Anweisung | ISAM | implementiert | tb-runtime::isam | bas7advr |
|
||||
| `DELETETABLE` | Anweisung | ISAM | implementiert | tb-runtime::isam | bas7advr |
|
||||
| `GETINDEX$` | Funktion | ISAM | implementiert | tb-runtime::isam | bas7advr |
|
||||
| `INSERT` | Anweisung | ISAM | implementiert | tb-runtime::isam | bas7advr |
|
||||
| `MOVEFIRST` | Anweisung | ISAM | implementiert | tb-runtime::isam | bas7advr |
|
||||
| `MOVELAST` | Anweisung | ISAM | implementiert | tb-runtime::isam | bas7advr |
|
||||
| `MOVENEXT` | Anweisung | ISAM | implementiert | tb-runtime::isam | bas7advr |
|
||||
| `MOVEPREVIOUS` | Anweisung | ISAM | implementiert | tb-runtime::isam | bas7advr |
|
||||
| `RETRIEVE` | Anweisung | ISAM | implementiert | tb-runtime::isam | bas7advr |
|
||||
| `ROLLBACK` | Anweisung | ISAM | implementiert | tb-runtime::isam | bas7advr |
|
||||
| `SAVEPOINT` | Funktion | ISAM | implementiert | tb-runtime::isam | bas7advr |
|
||||
| `SEEKEQ` | Anweisung | ISAM | implementiert | tb-runtime::isam | bas7advr |
|
||||
| `SEEKGE` | Anweisung | ISAM | implementiert | tb-runtime::isam | bas7advr |
|
||||
| `SEEKGT` | Anweisung | ISAM | implementiert | tb-runtime::isam | bas7advr |
|
||||
| `SETINDEX` | Anweisung | ISAM | implementiert | tb-runtime::isam | bas7advr |
|
||||
| `SETMEM` | Funktion | ISAM | implementiert | tb-runtime::isam | bas7advr |
|
||||
| `UPDATE` | Anweisung | ISAM | implementiert | tb-runtime::isam | bas7advr |
|
||||
| `CALLS` | Anweisung | Interlanguage | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
|
||||
| `SADD` | Funktion | Interlanguage | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
|
||||
| `SSEG` | Funktion | Interlanguage | Non-Feature | sprachreferenz.md#abweichungen | bas7advr |
|
||||
|
||||
@@ -259,11 +259,87 @@ solange ein Menü-Control den Fokus hat. Für Terminal Basic relevant:
|
||||
`LOC(n)`, `LOF(n)`.
|
||||
- Verwaltung: `NAME alt$ AS neu$`, `KILL datei$`, `FILES [muster$]`,
|
||||
`CHDIR`, `MKDIR`, `RMDIR`, `FILEATTR`, `FREEFILE`.
|
||||
- **ISAM** (Professional-Edition des Vorbilds): wird unterstützt
|
||||
(Entscheidung 2026-09-02) — `OPEN … FOR ISAM`, Tabellen/Indizes,
|
||||
`SEEKGT`-Familie usw.; Umfang wird mit dem Inventar (Phase 3) erfasst.
|
||||
- Pfade: plattformneutral; `/` und `\` werden akzeptiert.
|
||||
|
||||
## 10a. ISAM (indizierter Satzzugriff)
|
||||
|
||||
ISAM der Professional-Edition des Vorbilds wird unterstützt (Entscheidung
|
||||
2026-09-02). Das Dateiformat beschreibt
|
||||
[dateiformate.md](dateiformate.md#isam-datenbank-open--for-isam).
|
||||
|
||||
- `OPEN datenbank$ FOR ISAM typname tabellenname$ AS [#]n` bindet eine
|
||||
Tabelle an eine Dateinummer; die Felder des benannten `TYPE` sind ihre
|
||||
Spalten. Die Tabelle entsteht beim ersten Öffnen. `CLOSE` löst die
|
||||
Bindung; jede Operation außerhalb einer Transaktion ist für sich schon
|
||||
festgeschrieben. Eine laufende Transaktion lässt `CLOSE` unberührt —
|
||||
über ihr Ende entscheiden `COMMITTRANS` und `ROLLBACK ALL`; eine beim
|
||||
Programmende offene Transaktion bleibt wirkungslos.
|
||||
- Indizes: `CREATEINDEX [#]n, indexname$, eindeutig%, spalte$[, spalte$]…`,
|
||||
`DELETEINDEX [#]n, indexname$`, `SETINDEX [#]n[, indexname$]`,
|
||||
`GETINDEX$(n)`. `SETINDEX` ohne Namen wählt den NULL-Index
|
||||
(Einfügereihenfolge); `GETINDEX$` liefert dafür einen leeren String.
|
||||
- Sätze: `INSERT`, `RETRIEVE`, `UPDATE` (je `[#]n, satzvariable`) und
|
||||
`DELETE [#]n` auf dem aktuellen Satz.
|
||||
- Cursor: `MOVEFIRST`, `MOVELAST`, `MOVENEXT`, `MOVEPREVIOUS` (je `[#]n`)
|
||||
in der Ordnung des aktiven Index; `EOF(n)` und `BOF(n)` melden das
|
||||
Überlaufen am Ende bzw. am Anfang.
|
||||
- Suche: `SEEKEQ`, `SEEKGT`, `SEEKGE` (je `[#]n, schlüsselwert[, …]`).
|
||||
Ein mehrspaltiger Index lässt sich mit einem Präfix seiner Spalten
|
||||
durchsuchen; `SEEKEQ` mit unvollständigem Schlüssel schlägt dabei immer
|
||||
fehl (wie im Vorbild), `SEEKGE` und `SEEKGT` positionieren auf dem ersten
|
||||
passenden Satz. Über den NULL-Index lässt sich nicht suchen (Fehler 87).
|
||||
- Tabellen: `DELETETABLE datenbank$, tabellenname$`.
|
||||
- Transaktionen: `BEGINTRANS`, `COMMITTRANS`, `SAVEPOINT` (Funktion,
|
||||
liefert die Kennung), `ROLLBACK [kennung]` und `ROLLBACK ALL`.
|
||||
- `LOF(n)` liefert für eine ISAM-Dateinummer die Satzzahl der Tabelle,
|
||||
`LOC(n)` die Kennung des aktuellen Satzes (0 = unpositioniert).
|
||||
- Cursorlage wie im Vorbild: nach `SETINDEX` ist der erste Satz der neuen
|
||||
Ordnung der aktuelle; nach `DELETE` der auf den gelöschten folgende, und
|
||||
war der gelöschte der letzte, steht der Cursor am Ende der Tabelle ohne
|
||||
aktuellen Satz.
|
||||
- Fehlercodes 81–89 (`ERR`): 81 ungültiger Name, 82 Tabelle nicht
|
||||
gefunden, 83 Index nicht gefunden, 84 ungültige Spalte, 85 kein aktueller
|
||||
Satz, 86 Verstoß gegen einen eindeutigen Index, 87 unzulässige Operation
|
||||
auf dem NULL-Index (Suche), 88 Datenbank inkonsistent, 89 ISAM-Puffer zu
|
||||
klein.
|
||||
|
||||
**Sortierordnung der Indizes.** Textspalten ordnen nach
|
||||
**Unicode-Codepoints**; Groß- und Kleinschreibung werden **unterschieden**.
|
||||
Es ist dieselbe Ordnung, die der Vergleichsoperator des Dialekts auf
|
||||
Strings anwendet — ein Programm kann die Satzreihenfolge damit
|
||||
vorhersagen. Praktisch heißt das: alle Großbuchstaben `A`–`Z` stehen vor
|
||||
allen Kleinbuchstaben `a`–`z`, und Zeichen jenseits von ASCII (`Ä`, `ß`,
|
||||
`€`) stehen nach beiden, in der Reihenfolge ihrer Codepoints. Beispiel:
|
||||
`Apfel` < `Birne` < `apfel` < `birne` < `Äpfel`.
|
||||
|
||||
Eine sprachabhängige (locale-abhängige) Sortierung gibt es bewusst nicht:
|
||||
sie machte die Reihenfolge plattformabhängig. Das Vorbild ordnete nach den
|
||||
Zeichencodes einer festen Codepage; Codepoints sind die direkte
|
||||
Entsprechung unter der Unicode-Entscheidung dieses Projekts.
|
||||
|
||||
**Absteigende Indexspalten** (Erweiterung). Die Original-Hilfe kennt bei
|
||||
`CREATEINDEX` keine Sortierrichtung. Terminal Basic ordnet eine Spalte
|
||||
absteigend, wenn ihrem Namen ein `-` vorangestellt ist:
|
||||
|
||||
```basic
|
||||
CREATEINDEX #1, "NachPreis", 0, "Nachname", "-Preis"
|
||||
```
|
||||
|
||||
Das ist kollisionsfrei, weil ein Feldname einer `TYPE`-Anweisung nie mit
|
||||
`-` beginnen kann; Programme des Vorbilds bleiben unverändert gültig.
|
||||
|
||||
**`SETMEM` und Fehler 89** (Abweichung). Im Vorbild veränderte
|
||||
`SETMEM(n&)` den DOS-Fern-Heap um `n` Bytes. Ein DOS-Speichermodell gibt
|
||||
es hier nicht; stattdessen ist `SETMEM` die Obergrenze des ISAM-Puffers:
|
||||
sie wird um `n` Bytes verändert (negativ verkleinert, positiv vergrößert)
|
||||
und die danach verfügbare Größe geliefert. Der Vorgabewert ist **65536
|
||||
Bytes**. Gegen die Grenze zählen die Satzbytes einer laufenden Operation
|
||||
und das Rücknahmeprotokoll einer offenen Transaktion. Reicht der Puffer
|
||||
für eine Operation nicht aus, tritt Laufzeitfehler 89 („ISAM -
|
||||
Insufficient ISAM buffers") auf — nicht ein generischer Fehler und kein
|
||||
stiller Abbruch.
|
||||
|
||||
|
||||
## 11. Eingebaute Funktionen (Katalog)
|
||||
|
||||
**Strings:** `LEN`, `LEFT$`, `RIGHT$`, `MID$` (Funktion **und** Anweisung),
|
||||
|
||||
Reference in New Issue
Block a user