109 lines
2.8 KiB
Go
109 lines
2.8 KiB
Go
package models
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"reflect"
|
|
"strings"
|
|
|
|
"gorm.io/driver/postgres" // Für PostgreSQL
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// Globale Variable für die DB-Verbindung
|
|
var defaultDB *gorm.DB
|
|
|
|
// DatabaseConfig enthält die Konfigurationsdaten für die Datenbankverbindung
|
|
type DatabaseConfig struct {
|
|
Host string
|
|
Port int
|
|
User string
|
|
Password string
|
|
DBName string
|
|
SSLMode string
|
|
}
|
|
|
|
// InitDB initialisiert die Datenbankverbindung (einmalig beim Start)
|
|
// mit der übergebenen Konfiguration
|
|
func InitDB(config DatabaseConfig) error {
|
|
// DSN (Data Source Name) erstellen
|
|
dsn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=%s",
|
|
config.Host, config.Port, config.User, config.Password, config.DBName, config.SSLMode)
|
|
|
|
// Datenbankverbindung herstellen
|
|
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
|
|
if err != nil {
|
|
return fmt.Errorf("fehler beim Verbinden zur Datenbank: %w", err)
|
|
}
|
|
|
|
defaultDB = db
|
|
return nil
|
|
}
|
|
|
|
// GetEngine gibt die DB-Instanz zurück, ggf. mit context
|
|
func GetEngine(ctx context.Context) *gorm.DB {
|
|
// Falls in ctx eine spezielle Transaktion steckt, könnte man das hier prüfen
|
|
return defaultDB.WithContext(ctx)
|
|
}
|
|
|
|
// UpdateModel aktualisiert ein Modell anhand der gesetzten Pointer-Felder
|
|
func UpdateModel(ctx context.Context, model any, updates any) error {
|
|
updateValue := reflect.ValueOf(updates)
|
|
|
|
// Wenn updates ein Pointer ist, den Wert dahinter verwenden
|
|
if updateValue.Kind() == reflect.Ptr {
|
|
updateValue = updateValue.Elem()
|
|
}
|
|
|
|
// Stelle sicher, dass updates eine Struktur ist
|
|
if updateValue.Kind() != reflect.Struct {
|
|
return errors.New("updates muss eine Struktur sein")
|
|
}
|
|
|
|
updateType := updateValue.Type()
|
|
updateMap := make(map[string]any)
|
|
|
|
// Durch alle Felder iterieren
|
|
for i := 0; i < updateValue.NumField(); i++ {
|
|
field := updateValue.Field(i)
|
|
fieldType := updateType.Field(i)
|
|
|
|
// Überspringen von unexportierten Feldern
|
|
if !fieldType.IsExported() {
|
|
continue
|
|
}
|
|
|
|
// Spezialfall: ID-Feld überspringen (nur für Updates verwenden)
|
|
if fieldType.Name == "ID" {
|
|
continue
|
|
}
|
|
|
|
// Für Pointer-Typen prüfen, ob sie nicht nil sind
|
|
if field.Kind() == reflect.Ptr && !field.IsNil() {
|
|
// Feldname aus GORM-Tag extrahieren oder Standard-Feldnamen verwenden
|
|
fieldName := fieldType.Name
|
|
|
|
if tag, ok := fieldType.Tag.Lookup("gorm"); ok {
|
|
// Tag-Optionen trennen
|
|
options := strings.Split(tag, ";")
|
|
for _, option := range options {
|
|
if strings.HasPrefix(option, "column:") {
|
|
fieldName = strings.TrimPrefix(option, "column:")
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
// Den Wert hinter dem Pointer verwenden
|
|
updateMap[fieldName] = field.Elem().Interface()
|
|
}
|
|
}
|
|
|
|
if len(updateMap) == 0 {
|
|
return nil // Nichts zu aktualisieren
|
|
}
|
|
|
|
return GetEngine(ctx).Model(model).Updates(updateMap).Error
|
|
}
|