Skip to content

Commit c50bbe5

Browse files
author
Magrathean UK
committed
fix(grafana): harden latest-reading queries
1 parent 2b349a1 commit c50bbe5

2 files changed

Lines changed: 32 additions & 3 deletions

File tree

grafana/dashboards/battery-health.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,7 +1089,7 @@
10891089
"editorMode": "code",
10901090
"format": "table",
10911091
"rawQuery": true,
1092-
"rawSql": "SELECT * FROM ((SELECT usable_battery_level, date\r\nFROM positions\r\nWHERE car_id = $car_id AND ideal_battery_range_km IS NOT NULL AND usable_battery_level IS NOT NULL\r\nORDER BY date DESC\r\nLIMIT 1)\r\nUNION\r\n(SELECT usable_battery_level, date\r\nFROM charges c\r\nJOIN charging_processes p ON p.id = c.charging_process_id\r\nWHERE p.car_id = $car_id AND usable_battery_level IS NOT NULL\r\nORDER BY date DESC\r\nLIMIT 1)) AS last_usable_battery_level LIMIT 1",
1092+
"rawSql": "SELECT * FROM ((SELECT usable_battery_level, date\r\nFROM positions\r\nWHERE car_id = $car_id AND ideal_battery_range_km IS NOT NULL AND usable_battery_level IS NOT NULL\r\nORDER BY date DESC\r\nLIMIT 1)\r\nUNION ALL\r\n(SELECT c.usable_battery_level, date\r\nFROM charges c\r\nJOIN charging_processes p ON p.id = c.charging_process_id\r\nWHERE p.car_id = $car_id AND c.usable_battery_level IS NOT NULL\r\nORDER BY date DESC\r\nLIMIT 1)) AS last_usable_battery_level ORDER BY date DESC LIMIT 1",
10931093
"refId": "SOC",
10941094
"sql": {
10951095
"columns": [
@@ -1365,7 +1365,7 @@
13651365
"editorMode": "code",
13661366
"format": "table",
13671367
"rawQuery": true,
1368-
"rawSql": "SELECT * FROM ((SELECT usable_battery_level * ('$aux'::json ->> 'CurrentCapacity')::float / 100 as kWh, date, ('$aux'::json ->> 'CurrentCapacity')::float as Total\nFROM positions\nWHERE car_id = $car_id AND ideal_battery_range_km IS NOT NULL AND usable_battery_level IS NOT NULL\nORDER BY date DESC\nLIMIT 1)\nUNION\n(SELECT c.usable_battery_level * ('$aux'::json ->> 'CurrentCapacity')::float / 100 as kWh, date, ('$aux'::json ->> 'CurrentCapacity')::float as Total\nFROM charges c\nJOIN charging_processes p ON p.id = c.charging_process_id\nWHERE p.car_id = $car_id AND c.usable_battery_level IS NOT NULL\nORDER BY date DESC\nLIMIT 1)) AS last_usable_battery_level LIMIT 1",
1368+
"rawSql": "SELECT * FROM ((SELECT usable_battery_level * ('$aux'::json ->> 'CurrentCapacity')::float / 100 as kWh, date, ('$aux'::json ->> 'CurrentCapacity')::float as Total\nFROM positions\nWHERE car_id = $car_id AND ideal_battery_range_km IS NOT NULL AND usable_battery_level IS NOT NULL\nORDER BY date DESC\nLIMIT 1)\nUNION ALL\n(SELECT c.usable_battery_level * ('$aux'::json ->> 'CurrentCapacity')::float / 100 as kWh, date, ('$aux'::json ->> 'CurrentCapacity')::float as Total\nFROM charges c\nJOIN charging_processes p ON p.id = c.charging_process_id\nWHERE p.car_id = $car_id AND c.usable_battery_level IS NOT NULL\nORDER BY date DESC\nLIMIT 1)) AS last_usable_battery_level ORDER BY date DESC LIMIT 1",
13691369
"refId": "A",
13701370
"sql": {
13711371
"columns": [

test/teslamate/grafana/dashboard_queries_test.exs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ defmodule TeslaMate.Grafana.DashboardQueriesTest do
1313
#
1414
# `(?:(?!\bfrom\b).)*?` keeps a match from spilling across into a following
1515
# `FROM charges`/CTE, so the filter must appear inside the *same* positions block.
16-
@latest_position_block ~r/from positions\b(?:(?!\bfrom\b).)*?order by date desc(?:(?!\bfrom\b).)*?limit 1/
16+
@latest_position_block ~r/from positions\b(?:(?!\bfrom\b).)*?order by date desc(?:(?!\bfrom\b).)*?limit 1\b/
1717

1818
test "latest position queries use complete position rows" do
1919
offenders =
@@ -48,6 +48,35 @@ defmodule TeslaMate.Grafana.DashboardQueriesTest do
4848
assert unfiltered_latest_position_blocks(query) == []
4949
end
5050

51+
test "detector ignores queries with a larger limit" do
52+
query = "SELECT date FROM positions WHERE car_id = 1 ORDER BY date DESC LIMIT 10"
53+
54+
assert unfiltered_latest_position_blocks(query) == []
55+
end
56+
57+
test "latest usable battery unions select the newest source row" do
58+
queries =
59+
"grafana/dashboards/battery-health.json"
60+
|> dashboard_queries()
61+
|> Enum.map(fn {_path, query} ->
62+
query
63+
|> String.downcase()
64+
|> String.replace(~r/\s+/, " ")
65+
end)
66+
|> Enum.filter(&String.contains?(&1, "last_usable_battery_level"))
67+
68+
assert length(queries) == 2
69+
70+
for query <- queries do
71+
assert String.contains?(query, "union all")
72+
73+
assert String.contains?(
74+
query,
75+
"as last_usable_battery_level order by date desc limit 1"
76+
)
77+
end
78+
end
79+
5180
defp dashboard_queries(path) do
5281
path
5382
|> File.read!()

0 commit comments

Comments
 (0)