# MOSAIC Datenbanken und automatische Engine-Ermittlung

## Zweck

Dieses Dokument beschreibt den aktuellen Stand des MOSAIC-Kerns fuer:

- die direkt unterstuetzten Datenbanken
- die verwendeten Konfigurationsschluessel
- die Aufloesung des SQL-Zieltyps im Kern
- die Abgrenzung zwischen Datenbanktyp, SQL-Dialekt und MySQL-Storage-Engine

Stand: April 2026

## Grundbegriffe

In MOSAIC muessen drei Ebenen sauber auseinandergehalten werden:

| Ebene | Ort | Beispiel | Bedeutung |
|---|---|---|---|
| Verbindungs-Typ | `db_connection.lic` | `type = 'pgsql'` oder `type = 'oracle'` | PDO-Treiber und DSN-Aufbau |
| Modul-Dialekt | `*_form.cfg`, `*_grid.cfg`, weitere Modul-Configs | `db_typ = 'pgsql'` oder `db_typ = 'oracle'` | SQL-Zieltyp fuer Runner, Generatoren und SQL-Konvertierung |
| Effektiver DB-Typ | intern im Kern | `pgsql` oder `oracle` | tatsaechlich verwendeter Dialekt nach Normalisierung |

Wichtig:

- In MOSAIC wird fuer Modulkonfigurationen nur noch `db_typ` verwendet.
- In `db_connection.lic` bleibt der Verbindungsschluessel weiterhin `type`.

## Direkt unterstuetzte Datenbanken im Verbindungskern

Die Funktion `getDbConnection()` unterstuetzt im aktuellen Kern direkt diese Verbindungstypen:

- `mysql`
- `pgsql`
- `oracle`
- `sqlite`

Das bedeutet:

- MySQL und MariaDB werden ueber `type = 'mysql'` angebunden.
- PostgreSQL wird ueber `type = 'pgsql'` angebunden.
- Oracle wird ueber `type = 'oracle'` angebunden.
- SQLite wird ueber `type = 'sqlite'` angebunden.

Wichtig fuer Oracle:

- Oracle benoetigt den PDO-Treiber `pdo_oci`.

Wichtig fuer SQLite:

- SQLite benoetigt den PDO-Treiber `pdo_sqlite`.
- Ohne `pdo_sqlite` kann MOSAIC keine SQLite-Verbindung aufbauen.
- `db_edit.php` prueft das Vorhandensein dieses Treibers explizit, bevor eine SQLite-Verbindung gespeichert werden kann.

Beispiel fuer `db_connection.lic`:

```php
return [
    'default' => [
        'type' => 'pgsql',
        'host' => '127.0.0.1',
        'port' => '5432',
        'user' => '...',
        'pass' => '...',
    ],
];
```

## Admin-Verbindungsdialog `db_edit.php`

Die projektbezogene Verbindungsverwaltung in `_pgm/admin/db_edit.php` bietet aktuell diese Typen an:

- `MySQL / MariaDB`
- `PostgreSQL`
- `Oracle`
- `SQLite`

Der Dialog ist bewusst an den Verbindungskern angepasst und erlaubt nur Typen, die auch von `getDbConnection()` direkt verarbeitet werden.

### Verhalten bei MySQL / MariaDB

- Eingabefelder: Datenbankname, Host, Port, User, Passwort
- Standard-Port: `3306`

### Verhalten bei PostgreSQL

- Eingabefelder: Datenbankname, Host, Port, User, Passwort
- Standard-Port: `5432`
- Im Kern wird fuer PostgreSQL durchgaengig der Dialekt `pgsql` verwendet.

### Verhalten bei Oracle

- Eingabefelder: Datenbankname, Host, Port, User, Passwort
- Standard-Port: `1521`
- Im Kern wird fuer Oracle durchgaengig der Dialekt `oracle` verwendet.

### Verhalten bei SQLite

- Das Feld `Host` wird im Dialog funktional als Dateipfad zur SQLite-Datei verwendet.
- `Port`, `user` und `Passwort` werden im Dialog ausgeblendet, weil sie fuer den normalen SQLite-Betrieb nicht benoetigt werden.
- Beim Speichern werden diese Werte serverseitig ebenfalls verworfen.

### Treiberpruefung fuer SQLite

`db_edit.php` prueft bei Auswahl von `SQLite`, ob der PDO-Treiber `pdo_sqlite` verfuegbar ist.

Wenn `pdo_sqlite` fehlt:

- zeigt der Dialog sofort eine Fehlermeldung an
- der Speichern-Button wird deaktiviert
- serverseitig wird das Speichern trotzdem zusaetzlich blockiert

Damit ist sichergestellt, dass SQLite nicht nur optisch auswaehlbar ist, sondern nur dann verwendet werden kann, wenn die PHP-Umgebung den Treiber auch wirklich geladen hat.

### Anlegen einer neuen SQLite-Datei

Wenn in `db_edit.php` bei `SQLite` ein Dateipfad angegeben wird und die Datei noch nicht existiert, arbeitet MOSAIC zweistufig:

1. Die Maske meldet, dass die Datei noch nicht existiert.
2. Danach wird explizit gefragt, ob die SQLite-Datenbank jetzt angelegt werden soll.

Erst nach dieser Bestaetigung wird die Datei per PDO angelegt und die Verbindung gespeichert.

Zusatzpruefungen:

- Zeigt der Pfad auf ein Verzeichnis, wird dies als Fehler abgewiesen.
- Existiert das Zielverzeichnis noch nicht, wird die Anlage ebenfalls mit Fehlermeldung abgebrochen.

## Zulaessige `db_typ`-Werte im Kern

Im Modulkontext arbeitet MOSAIC mit `db_typ`.
Aktuell sind im Kern oder in der SQL-Konvertierung diese Zieltypen relevant:

- `mysql`
- `mariadb`
- `pgsql`
- `oracle`
- `sqlite`
- `sqlite_3.35+`
- `mssql`

Wichtige Einschraenkung:

- Nicht jeder dieser Werte ist gleichzeitig ein direkt unterstuetzter Verbindungstyp in `getDbConnection()`.
- Der Verbindungskern ist aktuell auf `mysql`, `pgsql`, `oracle` und `sqlite` begrenzt.
- Weitere Werte werden vor allem als SQL-Zieltypen in `convert_mysql_to_db_typ()` verwendet.

## Empfohlene Konfiguration in Modulen

Fuer neue MOSAIC-Module gilt:

- in `db_connection.lic`: `type`
- in Modulkonfigurationen: `db_typ`

Beispiel fuer ein Modul:

```php
return [
    'connection' => 'default',
    'db_typ' => 'pgsql',
    'table' => 'kunden',
    'primary_key' => 'kunden_id',
];
```

Dabei ist bewusst gewollt:

- `type = 'pgsql'` in der Verbindung
- `db_typ = 'pgsql'` im Modul

## Aufloesung des DB-Typs im Kern

### Grundidee

Wenn ein Modul mit `db_typ = 'pgsql'` oder `db_typ = 'oracle'` arbeitet, soll MOSAIC diese Datenbank im CRUD-Kern jeweils als einen gemeinsamen Dialekt behandeln.

### Ablauf im Kern

1. `getDbConnection()` baut die PDO-Verbindung anhand von `db_connection.lic` auf.
2. `iss_db_typ_from_pdo()` liest den PDO-Treiber ueber `PDO::ATTR_DRIVER_NAME`.
3. Bei PostgreSQL liefert der Kern immer `pgsql`, bei Oracle immer `oracle`.
4. `iss_module_db_typ()` normalisiert Modulwerte entsprechend auf den gemeinsamen Dialekt.

### Beteiligte Kernfunktionen

- `iss_db_typ_from_pdo(PDO $db)`
- `iss_module_db_typ(array $config, ?PDO $db = null, string $default = 'mysql')`
- `iss_normalize_db_typ($value, string $default = 'mysql')`

## Wie `iss_module_db_typ()` entscheidet

`iss_module_db_typ()` ist die zentrale Aufloesungsfunktion fuer Module.

Verhalten:

- Wenn im Modul `db_typ` gesetzt ist, wird dieser Wert normalisiert.
- Wenn kein `db_typ` gesetzt ist, faellt der Kern auf den Datenbanktreiber der aktiven Verbindung zurueck.
- Fuer PostgreSQL ist das Ergebnis im MOSAIC-Kern immer `pgsql`.
- Fuer Oracle ist das Ergebnis im MOSAIC-Kern immer `oracle`.

Das ist der gewollte Standard fuer neue Entwicklungen.

## SQL-Konvertierung im Kern

Viele konfigurierbare SQLs werden in MOSAIC weiterhin MySQL-nah formuliert und vor der Ausfuehrung an den effektiven DB-Typ angepasst.

Zentrale Funktion:

- `convert_mysql_to_db_typ($sql, $dbTyp)`

Typische Umsetzungen:

- Backticks nach PostgreSQL oder SQLite in doppelte Anfuehrungszeichen
- `NOW()` nach `CURRENT_TIMESTAMP`
- `IFNULL()` nach `COALESCE()`
- `CONCAT()` nach `||`

Wichtig:

- `sqlite` wird intern auf `sqlite_3.35+` normalisiert.
- PostgreSQL laeuft in der SQL-Konvertierung durchgaengig ueber den Dialekt `pgsql`.
- Oracle laeuft in der SQL-Konvertierung durchgaengig ueber den Dialekt `oracle`.

## Wo die Aufloesung bereits verwendet wird

Der aktuelle Kern nutzt die Aufloesung des DB-Typs bereits in mehreren Bereichen:

### CRUD und Form-Laufzeit

- `insertDatensatz()`
- `updateDatensatz()`
- `deleteDatensatz()`
- `copyDatensatz()`
- `form.php`

### SQL-Runtime und Lookups

- `grid.php`
- `pdf_export.php`
- `xls_export.php`
- `form_html.php`
- `grid_html.php`
- `show_chart.php`
- `show_calendar.php`

### Generatoren und Admin-Helfer

- `admin/create_grid.php`
- `admin/create_chart.php`

## Abgrenzung zur MySQL-Storage-Engine

Ein haeufiger Denkfehler ist, `db_typ` mit einer MySQL-Storage-Engine zu verwechseln.

Das ist falsch.

Beispiele:

- `db_typ = 'mysql'` beschreibt den SQL-Dialekt bzw. den Verbindungstyp.
- `InnoDB` oder `MyISAM` beschreiben die Speicher-Engine einer MySQL-Tabelle.

Das sind zwei verschiedene Ebenen.

Im Kern gilt deshalb:

- `mysql` ist ein Datenbank-/SQL-Typ
- `InnoDB` und `MyISAM` sind Tabellen-Engines

Die automatische Storage-Engine-Pruefung ist eine getrennte Zusatzlogik fuer die Form-Transaktionssteuerung.

## Entwickler-Regeln fuer neue Module

- In Modulkonfigurationen immer `db_typ` verwenden.
- In `db_connection.lic` immer `type` verwenden.
- Fuer PostgreSQL durchgaengig `db_typ = 'pgsql'` setzen.
- Fuer Oracle durchgaengig `db_typ = 'oracle'` setzen.
- SQL moeglichst im MOSAIC-Standard halten und bei Bedarf ueber `convert_mysql_to_db_typ()` laufen lassen.
- Neue Generatoren sollen Metadaten ueber `iss_list_tables()` und `iss_describe_table()` beziehen.
- Neue Laufzeitpfade sollen den Typ ueber `iss_module_db_typ()` oder `iss_db_typ_from_pdo()` ermitteln.

## Empfehlungen fuer PostgreSQL-Projekte

- In der Verbindungsdatei `type = 'pgsql'`
- In Modulen `db_typ = 'pgsql'`
- Generatoren und Runner nicht auf gesonderte PostgreSQL-Varianten verdrahten
- Dialektsonderfaelle nur im Kern zentral behandeln

Dadurch bleibt die Projektkonfiguration stabil und die CRUD-Logik eindeutig.

## Empfehlungen fuer Oracle-Projekte

- In der Verbindungsdatei `type = 'oracle'`
- In Modulen `db_typ = 'oracle'`
- Generatoren und Runner nicht auf gesonderte Oracle-Varianten verdrahten
- Dialektsonderfaelle nur im Kern zentral behandeln
- Die Erzeugung eigener Oracle-Primary-Keys kann ueber `onBeforeInsert` abgebildet werden.
- `sequence_name` bleibt als optionaler Komfortpfad fuer einfache Oracle-Sequenzen verfuegbar.

## Bekannte Grenzen des aktuellen Stands

- Der direkte Verbindungskern ist derzeit auf `mysql`, `pgsql`, `oracle` und `sqlite` begrenzt.
- MSSQL-Zieltypen existieren aktuell vor allem in der SQL-Konvertierung, nicht als voll ausgebauter Standard-Verbindungspfad.
- Die automatische MySQL-Storage-Engine-Ermittlung wird derzeit gezielt fuer die Form-Transaktionslogik verwendet, nicht als allgemeines Projekt-Feature fuer alle Runner.
- SQLite-Verbindungen im Admin setzen eine PHP-Umgebung mit geladenem `pdo_sqlite` voraus.

## Kurzfassung fuer Entwickler

Wenn nur drei Regeln im Kopf bleiben sollen, dann diese:

1. Verbindung ueber `type`, Modul ueber `db_typ`.
2. PostgreSQL und Oracle in MOSAIC immer als gemeinsamen Dialekt behandeln.
3. MySQL-Storage-Engines wie `InnoDB` oder `MyISAM` sind etwas anderes als der Modul-Dialekt und werden getrennt behandelt.