feat(refactor): adding database package
This commit is contained in:
@@ -2,11 +2,11 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"forge.cadoles.com/LaCanne/realZ/internal/config"
|
"forge.cadoles.com/LaCanne/realZ/internal/config"
|
||||||
|
"forge.cadoles.com/LaCanne/realZ/internal/database"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
_ "github.com/lib/pq" // Driver PostgreSQL
|
_ "github.com/lib/pq" // Driver PostgreSQL
|
||||||
@@ -41,29 +41,8 @@ type CorrectedAltitudeResponse struct {
|
|||||||
CorrectedZ float64 `json:"corrected_z"`
|
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.
|
// 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) {
|
return func(c *gin.Context) {
|
||||||
var input GpsCoord
|
var input GpsCoord
|
||||||
|
|
||||||
@@ -74,23 +53,22 @@ func getOrthometricCorrection(db *sql.DB) gin.HandlerFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// On appelle notre fonction utilitaire pour obtenir l'altitude.
|
// 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 {
|
if err != nil {
|
||||||
// Si aucune ligne n'est trouvée, ST_Value renvoie NULL, ce qui cause une erreur au Scan.
|
if err == sql.ErrNoRows {
|
||||||
// On peut considérer cette erreur comme un "non trouvé".
|
c.JSON(http.StatusNotFound, gin.H{"error": "Aucune donnée de correction trouvée pour ces coordonnées."})
|
||||||
// Pour une gestion plus fine, il faudrait vérifier le type d'erreur exact.
|
} else {
|
||||||
log.Printf("Erreur de la base de données ou aucune valeur trouvée: %v", err)
|
log.Printf("Erreur de la base de données: %v", err)
|
||||||
c.JSON(http.StatusNotFound, gin.H{"error": "Aucune donnée d'altitude trouvée pour ces coordonnées."})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "Erreur interne du serveur."})
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.IndentedJSON(http.StatusOK, AltitudeResponse{Z: altitude})
|
c.IndentedJSON(http.StatusOK, AltitudeResponse{Z: correction})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// getCorrectedAltitude est le handler pour la nouvelle route.
|
func getCorrectedAltitude(db *database.Service) gin.HandlerFunc {
|
||||||
// Il prend une altitude mesurée et retourne l'altitude corrigée.
|
|
||||||
func getCorrectedAltitude(db *sql.DB) gin.HandlerFunc {
|
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
var input GpsCoordWithZ
|
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).
|
// 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 {
|
if err != nil {
|
||||||
log.Printf("Erreur de la base de données ou aucune valeur trouvée: %v", err)
|
if err == sql.ErrNoRows {
|
||||||
c.JSON(http.StatusNotFound, gin.H{"error": "Aucune donnée de correction trouvée pour ces coordonnées."})
|
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
|
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() {
|
func main() {
|
||||||
cfg, err := config.Load()
|
cfg, err := config.Load()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error loading configuration: %v", err)
|
log.Fatalf("Error loading configuration: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
db, err := initDB(&cfg.Database)
|
db, err := database.NewService(&cfg.Database)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Could not initialize database: %v", err)
|
log.Fatalf("Could not initialize database: %v", err)
|
||||||
}
|
}
|
||||||
|
log.Println("Connected to PostgreSQL database")
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
router := gin.Default()
|
router := gin.Default()
|
||||||
|
Reference in New Issue
Block a user