fix: return real pagination totals
This commit is contained in:
@@ -102,6 +102,24 @@ func (r *MetricRepository) Query(ctx context.Context, query MetricQuery) ([]Metr
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
func (r *MetricRepository) Count(ctx context.Context, query MetricQuery) (int64, error) {
|
||||
query = normalizeMetricQuery(query)
|
||||
sqlText, args := buildMetricCountSQL(query)
|
||||
rows, err := r.db.QueryContext(ctx, sqlText, args...)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var total int64
|
||||
if rows.Next() {
|
||||
if err := rows.Scan(&total); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
return total, rows.Err()
|
||||
}
|
||||
|
||||
func normalizeMetricQuery(query MetricQuery) MetricQuery {
|
||||
query.VehicleKey = strings.TrimSpace(query.VehicleKey)
|
||||
query.VIN = strings.TrimSpace(query.VIN)
|
||||
@@ -116,6 +134,26 @@ func normalizeMetricQuery(query MetricQuery) MetricQuery {
|
||||
}
|
||||
|
||||
func buildMetricSQL(query MetricQuery) (string, []any) {
|
||||
where, args := buildMetricWhere(query)
|
||||
sqlText := `SELECT vehicle_key, vin, stat_date, protocol, metric_key, metric_value, metric_unit, first_total_mileage_km, latest_total_mileage_km, sample_count, calculation_method, created_at, updated_at FROM vehicle_daily_metric`
|
||||
if len(where) > 0 {
|
||||
sqlText += " WHERE " + strings.Join(where, " AND ")
|
||||
}
|
||||
sqlText += " ORDER BY stat_date DESC, vehicle_key ASC, protocol ASC, metric_key ASC LIMIT ? OFFSET ?"
|
||||
args = append(args, query.Limit, query.Offset)
|
||||
return sqlText, args
|
||||
}
|
||||
|
||||
func buildMetricCountSQL(query MetricQuery) (string, []any) {
|
||||
where, args := buildMetricWhere(query)
|
||||
sqlText := `SELECT COUNT(*) FROM vehicle_daily_metric`
|
||||
if len(where) > 0 {
|
||||
sqlText += " WHERE " + strings.Join(where, " AND ")
|
||||
}
|
||||
return sqlText, args
|
||||
}
|
||||
|
||||
func buildMetricWhere(query MetricQuery) ([]string, []any) {
|
||||
var where []string
|
||||
var args []any
|
||||
add := func(clause string, value any) {
|
||||
@@ -140,13 +178,7 @@ func buildMetricSQL(query MetricQuery) (string, []any) {
|
||||
if query.DateTo != "" {
|
||||
add("stat_date <= ?", query.DateTo)
|
||||
}
|
||||
sqlText := `SELECT vehicle_key, vin, stat_date, protocol, metric_key, metric_value, metric_unit, first_total_mileage_km, latest_total_mileage_km, sample_count, calculation_method, created_at, updated_at FROM vehicle_daily_metric`
|
||||
if len(where) > 0 {
|
||||
sqlText += " WHERE " + strings.Join(where, " AND ")
|
||||
}
|
||||
sqlText += " ORDER BY stat_date DESC, vehicle_key ASC, protocol ASC, metric_key ASC LIMIT ? OFFSET ?"
|
||||
args = append(args, query.Limit, query.Offset)
|
||||
return sqlText, args
|
||||
return where, args
|
||||
}
|
||||
|
||||
type MetricHandler struct {
|
||||
@@ -174,6 +206,11 @@ func (h *MetricHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
writeMetricError(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
total, err := h.repository.Count(r.Context(), query)
|
||||
if err != nil {
|
||||
writeMetricError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
rows, err := h.repository.Query(r.Context(), query)
|
||||
if err != nil {
|
||||
writeMetricError(w, http.StatusInternalServerError, err.Error())
|
||||
@@ -182,7 +219,7 @@ func (h *MetricHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{
|
||||
"items": rows,
|
||||
"total": len(rows),
|
||||
"total": total,
|
||||
"limit": query.Limit,
|
||||
"offset": query.Offset,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user