From 98d1aa66a91ce833049bb543a22ecd0e6b7351d9 Mon Sep 17 00:00:00 2001 From: Philippe Caseiro Date: Mon, 13 Oct 2025 11:27:47 +0200 Subject: [PATCH] feat(refactor): adding database package --- cmd/api/realz.go | 77 +++++++++++++----------------------------------- 1 file changed, 20 insertions(+), 57 deletions(-) diff --git a/cmd/api/realz.go b/cmd/api/realz.go index 25452d3..6a40121 100644 --- a/cmd/api/realz.go +++ b/cmd/api/realz.go @@ -2,11 +2,11 @@ package api import ( "database/sql" - "fmt" "log" "net/http" "forge.cadoles.com/LaCanne/realZ/internal/config" + "forge.cadoles.com/LaCanne/realZ/internal/database" "github.com/gin-gonic/gin" _ "github.com/lib/pq" // Driver PostgreSQL @@ -41,29 +41,8 @@ type CorrectedAltitudeResponse struct { CorrectedZ float64 `json:"corrected_z"` } -// queryAltitude interroge la base de données pour obtenir l'altitude réelle pour des coordonnées données. -// C'est une fonction utilitaire pour éviter la duplication de code. -func queryOrthometricCorrection(db *sql.DB, lat, lon float64, srcProj, dstProj int) (float64, error) { - var altitude float64 - - query := ` - SELECT ST_Value(rast, ST_Transform(ST_SetSRID(ST_MakePoint($2, $1), $3::integer), $4::integer)) AS pixel_value - FROM raf20lamber93 - WHERE ST_Intersects(rast, ST_Transform(ST_SetSRID(ST_MakePoint($2, $1), $3::integer), $4::integer)); - ` - - // On exécute la requête. QueryRow est idéal car nous attendons au plus une ligne. - err := db.QueryRow(query, lat, lon, srcProj, dstProj).Scan(&altitude) - if err != nil { - // Si aucune ligne n'est trouvée, ST_Value renvoie NULL, ce qui cause une erreur au Scan. - // On retourne l'erreur pour qu'elle soit gérée par la fonction appelante. - return 0, err - } - return altitude, nil -} - // getRealZ est le handler pour notre route. Il prend une connexion à la BDD en paramètre. -func getOrthometricCorrection(db *sql.DB) gin.HandlerFunc { +func getOrthometricCorrection(db *database.Service) gin.HandlerFunc { return func(c *gin.Context) { var input GpsCoord @@ -74,23 +53,22 @@ func getOrthometricCorrection(db *sql.DB) gin.HandlerFunc { } // On appelle notre fonction utilitaire pour obtenir l'altitude. - altitude, err := queryOrthometricCorrection(db, input.Lat, input.Lon, input.SrcProj, input.DstProj) + correction, err := db.QueryOrthometricCorrection(input.Lat, input.Lon, input.SrcProj, input.DstProj) if err != nil { - // Si aucune ligne n'est trouvée, ST_Value renvoie NULL, ce qui cause une erreur au Scan. - // On peut considérer cette erreur comme un "non trouvé". - // Pour une gestion plus fine, il faudrait vérifier le type d'erreur exact. - log.Printf("Erreur de la base de données ou aucune valeur trouvée: %v", err) - c.JSON(http.StatusNotFound, gin.H{"error": "Aucune donnée d'altitude trouvée pour ces coordonnées."}) + if err == sql.ErrNoRows { + c.JSON(http.StatusNotFound, gin.H{"error": "Aucune donnée de correction trouvée pour ces coordonnées."}) + } else { + log.Printf("Erreur de la base de données: %v", err) + c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur interne du serveur."}) + } return } - c.IndentedJSON(http.StatusOK, AltitudeResponse{Z: altitude}) + c.IndentedJSON(http.StatusOK, AltitudeResponse{Z: correction}) } } -// getCorrectedAltitude est le handler pour la nouvelle route. -// Il prend une altitude mesurée et retourne l'altitude corrigée. -func getCorrectedAltitude(db *sql.DB) gin.HandlerFunc { +func getCorrectedAltitude(db *database.Service) gin.HandlerFunc { return func(c *gin.Context) { var input GpsCoordWithZ @@ -101,10 +79,14 @@ func getCorrectedAltitude(db *sql.DB) gin.HandlerFunc { } // On appelle notre fonction utilitaire pour obtenir la correction orthométrique (N). - correction, err := queryOrthometricCorrection(db, input.Lat, input.Lon, input.SrcProj, input.DstProj) + correction, err := db.QueryOrthometricCorrection(input.Lat, input.Lon, input.SrcProj, input.DstProj) if err != nil { - log.Printf("Erreur de la base de données ou aucune valeur trouvée: %v", err) - c.JSON(http.StatusNotFound, gin.H{"error": "Aucune donnée de correction trouvée pour ces coordonnées."}) + if err == sql.ErrNoRows { + c.JSON(http.StatusNotFound, gin.H{"error": "Aucune donnée de correction trouvée pour ces coordonnées."}) + } else { + log.Printf("Erreur de la base de données: %v", err) + c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur interne du serveur."}) + } return } @@ -116,36 +98,17 @@ func getCorrectedAltitude(db *sql.DB) gin.HandlerFunc { } } -// initDB initializes and returns a database connection. -func initDB(cfg *config.DatabaseConfig) (*sql.DB, error) { - connStr := fmt.Sprintf("user=%s password=%s dbname=%s host=%s port=%d sslmode=%s", - cfg.User, cfg.Password, cfg.Dbname, - cfg.Host, cfg.Port, cfg.Sslmode, - ) - - db, err := sql.Open("postgres", connStr) - if err != nil { - return nil, fmt.Errorf("could not open database connection: %w", err) - } - - if err = db.Ping(); err != nil { - return nil, fmt.Errorf("could not ping database: %w", err) - } - - log.Println("Connected to PostgreSQL database") - return db, nil -} - func main() { cfg, err := config.Load() if err != nil { log.Fatalf("Error loading configuration: %v", err) } - db, err := initDB(&cfg.Database) + db, err := database.NewService(&cfg.Database) if err != nil { log.Fatalf("Could not initialize database: %v", err) } + log.Println("Connected to PostgreSQL database") defer db.Close() router := gin.Default()