SQLite Data Studio: Admin-Oberfläche
Zurück: SQLite Data Studio · Normative Regionsbelegung: SQLite Data Studio: Bereichs-Spezifikation (normativ)
[Live] Clean-Room-Nachbau (Azure Data Studio als UX-Vorbild, kein Fremdcode übernommen). Diese Seite beschreibt den funktionalen Ist-Stand aufgabenorientiert; die Region-für-Region-Sollstruktur (Shell-Aufbau, Aktionsinventar, Baum-Ikonen) ist auf der normativen Bereichs-Spezifikation verlinkt, nicht dupliziert.
Einschalten
enable_dbadmin ist seit 2026-08-25 standardmäßig an. Vorher stand es auf 0, mit
der Begründung, eine Datenbankoberfläche solle eine Installation nicht dadurch bekommen, dass
ein Plugin installiert wurde. Das stimmt für ein Paket, dessen Zweck ein anderer ist und das
einen Datenbankbildschirm nebenbei mitbringt — hier nicht: dieses Paket ist das Data
Studio. Ein Werkzeug, das aus ist, ist kein sichereres Werkzeug, sondern ein nicht
ausgeliefertes.
Der Bereich fehlt trotzdem? Dann hat die Instanz ihn abgeschaltet, und die Stelle ist
leicht zu übersehen: DokuWiki lädt conf/local.php und danach
conf/local.protected.php (inc/config_cascade.php), die geschützte Datei gewinnt also.
Eine Instanz kann in local.php eine 1 führen und den Bereich trotzdem aus haben. Lies
den wirksamen Wert, statt zwei Dateien zu durchsuchen.
Danach erscheint der Tab „Datenbank„ im Plugin-Admin — sichtbar nur, wenn das aktuelle Konto mindestens eine Fähigkeit der Berechtigungs- Matrix für diesen Bereich besitzt.
Shell-Aufbau
Alle Screens rendern innerhalb der geteilten .wkq-shell-Grid-Komposition aus
FluentUI: Basic Layout (vertieft): Objekt-Baum links (wo vorhanden), Inhalt mittig,
Eigenschaften-Auxbar rechts, Command-Bar oben, Statusleiste unten, rechte Modul-Rail für
screen-übergreifende Aktionen. Details zu Regionen/Farbsemantik/Rail-Aktionen:
SQLite Data Studio: Bereichs-Spezifikation (normativ) (normativ) und FluentUI: Admin-Bereich (vertieft)
(Verhaltensregeln).
Objekt-Explorer
Zeigt alle konfigurierten Verbindungen gleichzeitig als Wurzelknoten — die aktive (per
conn-Parameter) ist aufgeklappt, andere sind Wechsel-Links; nur die aktive Verbindung
wird tatsächlich geöffnet und introspiziert. Ein einziger, geteilter Baum-Partial über alle
fünf Views (Übersicht/Struktur/Browse/Workbench/Export).
- Knotentypen: Verbindung → Tabellen/Views → Spalten/Indizes/Fremdschlüssel/Trigger, je eigenes Icon-Set (Maskenbild-CSS, keine SVG-Datei-Ladungen).
- Kontextmenüs je Knotentyp (
rowActions()): u. a. „Öffnen“, „Browse„, „Struktur“, „Neue Tabelle„ (Verbindungs-Knoten), „Script as CREATE“/„Script as DROP„ (Tabellen/Views/Indizes), „Löschen“ (Tabellen/Views/Verbindung, über den Zwei-Schritt-Bestätigungsdialog). - Filterfeld unter der Titelleiste grenzt sichtbare Knoten per Substring ein (kein Ersatz für eine Server-Suche) — Details zum Baustein: Widget-Katalog → InputBox-Filter.
- Alles/Nichts einklappen über einen Kopfleisten-Umschalter.
Tabellen-Übersicht
Landing-Hub der aktiven Verbindung: Tabellenliste mit Zeilenzahl-Schätzung, je Zeile Browse/Struktur/Export/Löschen; Command-Bar-Aktion „Neue Tabelle„ (Zwei-Schritt-Drawer: Name → landet direkt im Table Designer für Feld 2 ff.).
Table Designer (Struktur-Ansicht)
Vier Register:
- Columns: Name und Typ direkt editierbar (Name-Änderung = Umbenennen, Typ-Änderung löst den Tabellen-Neuaufbau unten aus), Lösch-Checkbox je Zeile (Primärschlüssel serverseitig geschützt). Vorschau zeigt das exakte SQL vor Ausführung; Anwenden führt in einer Transaktion aus.
- Indexes: Liste + sofortiges Anlegen/Löschen (kein Vorschau-Schritt, da unkritisch).
- Foreign Keys (nur SQLite): Liste + Hinzufügen über Vorschau/Anwenden (kann bestehende Daten verletzen), Löschen sofort (kann nie verletzen).
- Triggers (nur SQLite, rein lesend): Name + vollständiger, hervorgehobener SQL-Quelltext je Trigger.
Jede Zeile (Columns/Indexes/Foreign Keys) trägt einen „Eigenschaften“-Link, der die rechte Auxiliary-Bar mit einem Property-Grid der Auswahl füllt — Klick-zum-Neuladen (AJAX-Fragment), kein Live-JS-Formular.
Tabellen-Neuaufbau (Rebuild)
SQLite kennt kein ALTER TABLE … ALTER COLUMN und kein nachträgliches
ADD CONSTRAINT — beides läuft über den offiziell dokumentierten 12-Schritte-Neuaufbau
(dbadmin/RebuildPlanner.php): neue Zieltabelle anlegen, Daten spaltenweise kopieren,
Indizes/Trigger wiederherstellen, PRAGMA foreign_key_check vor COMMIT (Verletzung →
vollständiger Rollback), alles in einer Transaktion. Zusätzlich vor jedem Neuaufbau eine
VACUUM INTO-Sicherungskopie der gesamten Datenbank (Pfad wird angezeigt, nie automatisch
gelöscht). Einspaltige INTEGER PRIMARY KEY-Spalten bleiben als Rowid-Alias erhalten
(Autoincrement-Verhalten).
Datenbrowser (Browse)
Paging + Spalten-Sortierung, jede Zeile mit „Eigenschaften„-Link (volle Zeile im Auxbar). Zeilen-Aktionen: Insert/Edit (Drawer-Formular, Werte gebunden, Identifikation über Primärschlüssel), Delete (Einzelzeile oder Mehrfachauswahl → Massenlöschen, beides über den Zwei-Schritt-Bestätigungsdialog mit Stichprobenanzeige).
Query-Workbench
Multi-Statement-SQL-Konsole. Ergebnis als eigener Results/Messages-Tabstreifen — Fehler-/Erfolgstext getrennt vom Ergebnis-Grid.
- Parameter-Dialog: unbenannte
:name-Platzhalter im SQL-Text werden erkannt und vor der Ausführung als Formular abgefragt (Pflichtfeld-Gate serverseitig, nicht nur per HTML5required); jeder Wert hat eine Listen-Alternative (<details>-Aufklapper) für IN-Filter. „Letzte Werte“ persistieren client-seitig, Secrets-verdächtige Feldnamen (pass/pwd/secret/token/…) werden davon ausgeschlossen. - Entwurfs-Persistenz: der SQL-Text selbst überlebt einen Tabwechsel/Neuladen über
localStorage(beforeunload-Warnung bei ungespeicherten Änderungen), unabhängig vom Parameter-Dialog. - Abfrage-Historie: Ring-Puffer je Verbindung (nur SQL-Text/Zeitpunkt/Dauer/Zeilenzahl — nie Werte), aus der rechten Modul-Rail erreichbar; „In Editor übernehmen„ je Eintrag.
- Routinen-Editor-Drawer: eine bestehende Routine direkt aus dem Objekt-Baum bearbeiten, ohne den Bereich „Routinen“ zu verlassen — zwei Register (JSON, Eigenschaften), Details: Dialog-Katalog.
- Als Routine speichern: ein erfolgreich gelaufenes Statement lässt sich direkt als neue benannte Routine ablegen — Parametertypen werden aus den erkannten Platzhaltern vorgeschlagen, im Routinen-Editor verfeinerbar.
Export
- Ergebnis-Export (CSV/JSON) direkt aus der Workbench: der Client sendet nie SQL-Text, nur einen SHA-256-Hash gegen den jüngsten Historien-Eintrag der Verbindung — ausführbar ist dadurch ausschließlich ein bereits über den gegateten Konsolen-Pfad gelaufenes Statement; ein veralteter Hash wird abgewiesen. Die Wiederausführung nutzt denselben Konsolen-Pfad, wodurch der Readonly-Modus automatisch mitgilt.
- Zeilen-Kopieren (Strg+C, mit/ohne Kopfzeile) und CSV-Massenexport direkt aus dem Ergebnis-/Browse-Raster — Formel-Injection-sicher (CWE-1236: Zellen, die mit
=+-@beginnen, bekommen ein führendes Apostroph). - Eigenständiger Export-Screen für Tabellen-/View-Exporte außerhalb der Workbench (CSV/JSON/SQL).
Dialog-Katalog
| Dialog | Zweck | Muster |
|---|---|---|
Bestätigungsdialog (ConfirmDialog) | Zwei-Schritt-Bestätigung für jede destruktive Aktion (Tabelle/View/Index/Fremdschlüssel/Verbindung/Routine löschen, Massenlöschen) | Echter Server-Roundtrip statt confirm() — die erste Einreichung mutiert nichts, zeigt nur Anzahl + Stichprobe (gedeckelt auf 20). Funktioniert identisch mit/ohne JavaScript. |
Parameter-Formular (ParamForm) | Werte für :name-Platzhalter sammeln — sowohl untypisiert (Workbench-Konsole) als auch typisiert (Routinen-Test aus dem Manifest) | Serverseitiges Pflichtfeld-Gate; Listen-Alternative über <details> |
Routinen-Editor (RoutineEditorForm) | Manifest bearbeiten: Register „JSON„ (Rohtext) und „Eigenschaften“ (Formularfelder — Rückgabetyp, Parameter-Tabelle, Implementierungen) | Echte Registerkarten-Links (nav-Modus), kein Client-Toggle — jedes Register ist ein eigenständiges Formular, nie Datenkonflikt zwischen Tabs. Beide Register speichern über denselben Manifest-Validator. |
Berechtigungs-Matrix (PolicyMatrixForm) | Fähigkeiten je Gruppe/Benutzer anzeigen, speichern, entfernen — global oder je Verbindung | Details: Berechtigungen → Matrix-Dialog |
| „Connect to…„ | Neue SQLite-Verbindung ohne Pfadeingabe anlegen | Details: Verbindungen |
Readonly-Modus
Option dbadmin_readonly=1 verbietet alle Schreibvorgänge (inkl. Tabellen-Neuaufbau) und
beschränkt die Konsole auf lesende Anweisungen (SELECT/PRAGMA/EXPLAIN/SHOW/
lesendes WITH … SELECT); ein portabler, quote-/kommentar-bewusster Tokenizer erkennt auch
verschleierte Schreibversuche (z. B. schreibende Common-Table-Expressions). Übersteuert immer
die Berechtigungs-Matrix — selbst eine explizit gewährte write/design-Fähigkeit greift
in diesem Modus nicht (Details:
Berechtigungen).
Weitere Betriebsoptionen
Alle neun Einstellungen dieses Bereichs, im Konfigurationsmanager unter plugin » wksqliteds.
Die drei Einstellungen für Routinen (allowPhp, default_connection, slow_ms)
gehören nicht hierher, sondern zu Routinen →
Konfiguration.
Zugang
| Option | Default | Bedeutung |
|---|---|---|
enable_dbadmin | 1 | Bereich „Datenbank“ überhaupt anbieten. An ausgeliefert seit 2026-08-25 — s. Einschalten |
dbadmin_readonly | 0 | Not-Aus für alle Schreibvorgänge — s. Readonly-Modus |
dbadmin_time_limit | 180 | Sekunden, die eine Anfrage an diesen Bildschirm laufen darf; 0 = PHPs eigenes Limit unangetastet lassen |
dbadmin_time_limit wirkt ausschließlich hier — einmal je Anfrage, in
admin.php::applyTimeLimit(), und nur bei einem Wert größer null. Keine andere Seite des Wikis
ist berührt.
Die Einstellung existiert, weil beliebiges SQL, Exporte und Sicherungen die einzige Arbeit dieser
Installation sind, die Minuten laufen kann — und sie gehören alle diesem Bereich. Der Wert stand
früher in der Wiki-Konfiguration, angehängt an eine unverwandte Zuweisung, und wirkte damit beim
Lesen jener Datei: bei jeder Anfrage und jedem Kommandozeilenlauf des ganzen Wikis. Er tat
dabei zweierlei zugleich, weil PHPs Ausgangswert von der Betriebsart abhängt — im Web anheben
(30 → 180), auf der Kommandozeile deckeln (0 → 180). Die zweite Hälfte hat den mitgelieferten
Suchindexer reproduzierbar getötet. Wer mehr Zeit braucht als hier, braucht sie in der
php.ini, wo ein Betreiber sie sieht.
Wie viele Zeilen
Drei Grenzen, die leicht verwechselt werden, weil alle drei „Zeilen„ zählen — sie zählen aber an drei verschiedenen Stellen:
| Option | Default | Begrenzt | 0 bedeutet |
|---|---|---|---|
dbadmin_max_result_rows | 1000 | wie viele Zeilen geholt werden (Konsole und Export) | unbegrenzt |
dbadmin_grid_rows | 1000 | wie viele Zeilen die Workbench zeichnet | unbegrenzt |
dbadmin_buffer_cache_rows | 200 | wie viele Zeilen je Puffer als letztes Ergebnis aufbewahrt werden | unbegrenzt |
dbadmin_page_size | 12 | Zeilen je Seite im Browse-Raster | — (mindestens 1) |
Warum Holen und Zeichnen getrennt sind. Jede Zeile des Ergebnisrasters wird ein echtes
<tr>; virtuelles Scrollen gibt es hier bewusst nicht. Ein unbegrenztes Ergebnis wird damit
zu einer unbegrenzten Seite — auf dieser Instanz gemessen: 32 767 Zeilen ergaben 1 MB HTML und
2,5 s Serverzeit, und ein größeres Ergebnis stirbt mitten in der Anfrage und lässt den Browser auf
der vorigen Seite stehen. Von außen sieht das aus wie „die Abfrage tut nichts“.
Der volle geholte Satz bleibt erreichbar: CSV- und JSON-Export lesen das Ergebnis, nicht das Raster. Greift die Zeichengrenze, nennt der Hinweis über dem Raster beide Zahlen — gezeichnet und geholt —, damit niemand die kleinere für das Ergebnis hält.
dbadmin_buffer_cache_rows ist ausdrücklich unabhängig von und kleiner als die beiden anderen:
Es ist eine Vorschau zum Weiterarbeiten beim Puffer-Wechsel, nicht die maßgebliche Darstellung.
Die entsteht bei jedem Lauf neu und folgt dabei immer der Holgrenze.
dbadmin_page_size steht auf 12, nicht auf 50. Diese Seite nannte bis zum 4. August 2026 den
Wert 50; das war die alte, paketeigene Zahl. Heute ist es die hausweite Rastervorgabe — jede Liste
des Produkts beginnt bei derselben Seitengröße, damit „ein Bildschirm sind zwölf Zeilen„ überall
dasselbe heißt. Erhöhen bleibt unterstützt: Ein Browse-Raster, das über das Sichtfenster
hinausgeht, lädt beim Scrollen weiter — eine größere Seite bedeutet also vor allem weniger
Anfragen, keine andere Bedienung.
Wie viele Register
| Option | Default | Begrenzt |
|---|---|---|
dbadmin_max_query_buffers | 20 | gleichzeitig offene Abfrage-Puffer je Benutzer und Verbindung |
dbadmin_max_workspace_tabs | 20 | gleichzeitig offene Struktur-, Browse- und Wartungs-Register je Benutzer und Verbindung |
Beide Grenzen zählen getrennt. Das ist der Zweck: Wer viele Tabellenstrukturen öffnet, kann damit keine offenen Abfrage-Puffer verdrängen, und umgekehrt.
Ein stillschweigend geschlossener Puffer wäre der teurere Ausgang: Er trifft immer den Puffer, an dem gerade nicht gearbeitet wurde, und meldet sich nie.
Schema-Metadaten kommen über einen per-Backend-SchemaIntrospector (SQLite:
sqlite_master/PRAGMA; MySQL/PgSQL/SQL-Server: information_schema/Katalog; MS
Access: Best-Effort via ODBC).
Verwandte Themen
- SQLite Data Studio: Bereichs-Spezifikation (normativ) — normative Regionsbelegung, Aktionsinventar, Baum-Ikonen
- SQLite Data Studio: Berechtigungen — wer welchen Screen/welche Aktion sieht
- FluentUI: Admin-Bereich (vertieft) — Shell-Verhaltensregeln, Drawer-Regel
- SQLite Data Studio: How-to — Rezepte „Historie nutzen“, „Script as„
Verifiziert gegen: wk-dw-sqliteds-plugin@a84984f (2026-07-15).