package database import ( "context" "crypto/md5" "database/sql" "encoding/hex" "fmt" "math" "time" ) // UpsertRadarTile stores a radar tile into table `radar_tiles`. // Assumes the table exists with schema compatible to columns used below. func UpsertRadarTile(ctx context.Context, db *sql.DB, product string, dt time.Time, z, y, x int, width, height int, data []byte) error { if width == 0 { width = 256 } if height == 0 { height = 256 } step := 360.0 / math.Pow(2, float64(z)) west := -180.0 + float64(x)*step south := -90.0 + float64(y)*step east := west + step north := south + step res := step / float64(width) sum := md5.Sum(data) md5hex := hex.EncodeToString(sum[:]) q := ` INSERT INTO radar_tiles ( product, dt, z, y, x, width, height, west, south, east, north, res_deg, data, checksum_md5 ) VALUES ( $1,$2,$3,$4,$5,$6,$7, $8,$9,$10,$11,$12, $13,$14 ) ON CONFLICT (product, dt, z, y, x) DO UPDATE SET width = EXCLUDED.width, height = EXCLUDED.height, west = EXCLUDED.west, south = EXCLUDED.south, east = EXCLUDED.east, north = EXCLUDED.north, res_deg = EXCLUDED.res_deg, data = EXCLUDED.data, checksum_md5 = EXCLUDED.checksum_md5` _, err := db.ExecContext(ctx, q, product, dt, z, y, x, width, height, west, south, east, north, res, data, md5hex, ) if err != nil { return fmt.Errorf("upsert radar tile (%s %s z=%d y=%d x=%d): %w", product, dt.Format(time.RFC3339), z, y, x, err) } return nil }