edu-senex/edu/content/flashcards/deck-postgresql.md

10 KiB

Flashcard Deck: PostgreSQL Grundlagen & Konfiguration

Thema: PostgreSQL-spezifisches Wissen fuer Solution2-Entwickler Schwierigkeit: Anfaenger -> Fortgeschritten Karten: 20


Karte 1 | Basis

Q: Welcher DAM (Data Access Module) wird fuer PostgreSQL in Omnis verwendet? A: PGSQLDAM (auch als PostgresDAM in der INI-Datei). Omnis laedt die Bibliothek dampgsql.so (Linux) bzw. dampgsql.dll (Windows), die wiederum libpq (die offizielle PostgreSQL-Client-Bibliothek) nutzt.


Karte 2 | Basis

Q: Was ist libpq und warum ist es fuer Solution2 wichtig? A: libpq ist die offizielle C-Client-Bibliothek von PostgreSQL. Omnis' dampgsql.so nutzt dlopen() um libpq zur Laufzeit zu laden. Ohne libpq crasht Omnis beim Datenbankzugriff mit "double free or corruption" (SIGABRT) oder "general protection fault" (SIGSEGV). In Docker muss ein Symlink erstellt werden: ln -s /usr/lib/x86_64-linux-gnu/libpq.so.5 /opt/omnis/libpq.so


Karte 3 | Basis

Q: Wie sieht die PostgreSQL-Verbindungskonfiguration in der Solution2-INI-Datei aus? A: ``` [SQL] Database=PostgreSQL DatabaseName=masterdemo HostIP=postgres HostPort=5432 UserName=soluser DAM=PostgresDAM Schema=soluser

**ACHTUNG:** Es muss `HostPort` heissen, NICHT `Port`! Omnis liest `$getSectionParameter('SQL','HostPort')`.

---

## Karte 4 | Basis
**Q:** Welche Standard-Rollen gibt es in einer Solution2 PostgreSQL-Datenbank?
**A:** - `sol2_system`: Schema-Owner, erstellt Tabellen und Objekte
- `soluser`: Anwendungsbenutzer mit CRUD-Rechten, wird von Omnis verwendet
- Optional: `kunde_readonly`: Lesezugriff fuer Reporting/Monitoring.
Rechte werden ueber `ALTER DEFAULT PRIVILEGES` automatisch vergeben: `ALTER DEFAULT PRIVILEGES FOR ROLE sol2_system GRANT ALL ON TABLES TO soluser;`

---

## Karte 5 | Basis
**Q:** Was ist der Unterschied zwischen `$logon()` und `$execdirect()` in Omnis?
**A:** - `$logon()` erstellt eine **persistente Datenbank-Session** mit voller Transaktionskontrolle ($begin/$commit/$rollback)
- `$execdirect()` fuehrt ein **einzelnes SQL-Statement** direkt aus, mit Auto-Commit.
Fuer alles was zusammenhaengt (z.B. Auftrag + Positionen anlegen) MUSS eine Session mit expliziter Transaktion verwendet werden.

---

## Karte 6 | Basis
**Q:** Wie funktioniert eine Transaktion in Omnis/Solution2?
**A:** ```omnis
Do lSess.$begin() Returns #F        ;; START TRANSACTION
  Do lStmt.$execdirect(lSQL1) Returns #F
  Do lStmt.$execdirect(lSQL2) Returns #F
If lAllesOK
  Do lSess.$commit() Returns #F     ;; COMMIT
Else
  Do lSess.$rollback() Returns #F   ;; ROLLBACK
End If

Immer #F (flag) pruefen! Bei Fehler sofort $rollback().


Karte 7 | Mittel

Q: Was sind die wichtigsten PostgreSQL-Tuning-Parameter fuer Solution2? A: - shared_buffers = 25% RAM (Cache fuer Tabellendaten)

  • effective_cache_size = 75% RAM (Planer-Hint fuer OS-Cache)
  • work_mem = RAM / (max_connections * 4) (pro Query-Sortierung)
  • maintenance_work_mem = RAM / 32 (fuer VACUUM, CREATE INDEX)
  • max_connections = 100 (Standard, reicht fuer Omnis + n8n + pgAdmin)
  • log_min_duration_statement = 250ms (Slow-Query-Logging)

Karte 8 | Mittel

Q: Was passiert wenn in PostgreSQL ein SELECT ohne Transaktion laeuft? A: PostgreSQL wrapt jedes einzelne Statement automatisch in eine Transaktion (Auto-Commit). Das bedeutet: Ein einzelnes SELECT sieht immer einen konsistenten Snapshot. Aber wenn du ZWEI aufeinanderfolgende SELECTs ohne explizite Transaktion machst, koennen sie unterschiedliche Daten sehen, weil dazwischen ein anderer Benutzer etwas geaendert haben kann.


Karte 9 | Mittel

Q: Was sind die PostgreSQL Isolation Levels und welcher wird in Solution2 typisch verwendet? A: - READ COMMITTED (Standard in PostgreSQL und Solution2): Jedes Statement sieht nur Daten die VOR dem Statement committed wurden

  • REPEATABLE READ: Die gesamte Transaktion sieht den Snapshot vom Transaktionsbeginn
  • SERIALIZABLE: Strengste Isolation, verhindert Phantom Reads. Solution2 nutzt den Standard READ COMMITTED. Das reicht fuer die meisten ERP-Operationen.

Karte 10 | Mittel

Q: Was ist der Unterschied zwischen einer PostgreSQL SEQUENCE und einem Auto-Increment? A: In PostgreSQL gibt es kein echtes "Auto-Increment". Stattdessen:

  • SERIAL / BIGSERIAL: Erstellt automatisch eine Sequence und setzt DEFAULT nextval('seq_name')
  • GENERATED ALWAYS AS IDENTITY: Moderner Standard (PostgreSQL 10+), verhindert manuelle Werte
  • SEQUENCE: Eigenstaendiges Datenbankobjekt, kann von mehreren Tabellen geteilt werden. Solution2 nutzt haeufig eigene Counter-Tabellen statt Sequences, um Nummernkreise flexibler zu steuern.

Karte 11 | Mittel

Q: Wie funktioniert Soft-Delete in Solution2 und warum wird es verwendet? A: Jede Solution2-Tabelle hat eine Spalte valid (BOOLEAN). Statt DELETE FROM parts WHERE id = 42 wird UPDATE parts SET valid = false WHERE id = 42 verwendet. Gruende:

  • Referenzielle Integritaet bleibt erhalten (Foreign Keys zeigen noch auf den Datensatz)
  • Historische Daten bleiben fuer Reports verfuegbar
  • Versehentliches Loeschen ist reversibel. WICHTIG: Bei SELECTs immer WHERE valid = true filtern!

Karte 12 | Mittel

Q: Welche Audit-Spalten hat jede Solution2-Tabelle? A: - created (TIMESTAMP): Wann wurde der Datensatz erstellt

  • modtime (TIMESTAMP): Letzte Aenderung
  • revisor (INTEGER): ID des Benutzers der zuletzt geaendert hat
  • valid (BOOLEAN): Soft-Delete Flag (true = aktiv, false = geloescht) Diese Spalten werden automatisch von den T_Super-Methoden befuellt. Nie manuell setzen!

Karte 13 | Fortgeschritten

Q: Warum darf man Stammdaten (Artikel, Mitarbeiter, Adressen) NICHT per SQL-INSERT anlegen? A: Solution2 erstellt beim Anlegen automatisch abhaengige Datensaetze:

  • Artikel: Versionseintraege, Lifecycle, Lagerzuordnungen, Zusatzfeld-Defaults, Audit-Trail, Stuecklistenstrukturen
  • Mitarbeiter: Gruppenzuordnungen, Berechtigungen, Passwort-Records, Personaldaten
  • Adressen: Zahlungsbedingungen, Kommunikationseintraege, Rollenzuordnungen. Ein SQL-INSERT erzeugt nur den Hauptdatensatz — die abhaengigen Daten fehlen, was zu Fehlern und inkonsistenten Zustaenden fuehrt. Richtig: Ueber Solution2-UI oder rtDataImport-Service.

Karte 14 | Fortgeschritten

Q: Was ist T_Super in Solution2? A: T_Super ist die Basis-Tabellenklasse von der alle Tabellen-Klassen erben. Sie stellt gemeinsame Methoden bereit:

  • $select(): Daten laden mit automatischer Schema/WHERE-Behandlung
  • $insert(): Neuen Datensatz anlegen (setzt created, modtime, revisor automatisch)
  • $update(): Datensatz aendern (aktualisiert modtime und revisor)
  • $delete(): Soft-Delete (setzt valid = false). Es gibt auch T_SuperVersion fuer versionierte Tabellen (z.B. Artikelstaemme mit Aenderungshistorie).

Karte 15 | Fortgeschritten

Q: Was darf man per SQL aendern und was nicht? A: Erlaubt (UPDATE):

  • Enterprise-Daten (Firmenstamm), SystemKey, DBStatus
  • Nummernkreise zuruecksetzen (UPDATE nextnumber)
  • Konfigurationstabellen (Warengruppen, Zusatzfelder)
  • Passwort-Reset Erlaubt (DELETE/TRUNCATE):
  • Bewegungsdaten (Auftraege, Rechnungen) wenn sicher VERBOTEN (INSERT):
  • Artikel, Mitarbeiter, Adressen, Dokumente — immer ueber Solution2 UI oder Services!

Karte 16 | Fortgeschritten

Q: Wie behandelt Solution2 BLOBs (Binary Large Objects) in PostgreSQL? A: BLOBs werden in der Tabelle documentcontent gespeichert (z.B. angehaengte PDFs, Bilder). Bei der Migration von FrontBase nach PostgreSQL gibt es zwei Strategien:

  • Phase-1 (Inline): BLOBs direkt mit den Daten importieren — einfach, aber langsam bei grossen DBs (> 2GB)
  • Phase-2 (Separat): Erst Struktur + Daten, dann BLOBs nachtraeglich importieren — empfohlen fuer Produktion. PostgreSQL speichert grosse BLOBs via TOAST (The Oversized Attribute Storage Technique) automatisch komprimiert.

Karte 17 | Fortgeschritten

Q: Was ist TOAST in PostgreSQL? A: TOAST (The Oversized Attribute Storage Technique) ist PostgreSQLs Mechanismus fuer grosse Feldwerte. Wenn ein Wert groesser als ca. 2kB ist, wird er automatisch:

  1. Erst komprimiert (LZ-Kompression)
  2. Wenn immer noch zu gross: In eine separate TOAST-Tabelle ausgelagert. Das passiert transparent — fuer die Anwendung sieht es aus wie ein normales Feld. Relevant fuer Solution2s documentcontent-Tabelle mit grossen Anhaengen.

Karte 18 | Fortgeschritten

Q: Wie funktioniert die Fehlerbehandlung bei SQL-Operationen in Omnis? A: ```omnis Do lStmt.$execute(lParam) Returns #F If not(flag true) Calculate lCode as lSess.$lasterror Calculate lText as lSess.$lasterrortext OK message {SQL-Fehler [lCode]: [lText]} Do lSess.$rollback() Returns #F End If

**Wichtig:** `#F` (flag) wird nach JEDER SQL-Operation gesetzt. `$lasterror` liefert den PostgreSQL-Fehlercode, `$lasterrortext` die lesbare Meldung. Bei Deadlocks (error code 40P01) kann ein Retry sinnvoll sein.

---

## Karte 19 | Fortgeschritten
**Q:** Was muss man bei Docker-Deployments fuer die PostgreSQL-Verbindung beachten?
**A:** - `HostIP` in der INI muss der **Docker-Container-Name** sein (z.B. `postgres`), NICHT `localhost` oder `127.0.0.1`
- Alle Container muessen im gleichen Docker-Network sein (z.B. `senex-net`)
- `libpq.so` muss als Symlink im Omnis-Home-Verzeichnis existieren
- `pg_hba.conf` muss Verbindungen vom Docker-Netzwerk erlauben: `host all all 172.16.0.0/12 scram-sha-256`
- Session-Timeouts beachten: PostgreSQL schliesst idle Connections nach `idle_in_transaction_session_timeout`

---

## Karte 20 | Fortgeschritten
**Q:** Wie prueft man in PostgreSQL langsame Queries und was bedeutet das fuer Solution2?
**A:** ```sql
-- Slow Query Log aktivieren (postgresql.conf)
log_min_duration_statement = 250  -- Alles > 250ms loggen

-- Ausfuehrungsplan anzeigen
EXPLAIN ANALYZE SELECT * FROM orders WHERE valid = true AND status = 'A';

-- Laufende Queries anzeigen
SELECT pid, now() - pg_stat_activity.query_start AS duration, query
FROM pg_stat_activity WHERE state = 'active';

Typische Solution2-Bottlenecks: Fehlende Indizes auf valid-Spalte, grosse JOINs ueber orders/orderitems ohne Einschraenkung, LIKE-Suchen ohne Index.