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 }