mirror of
https://github.com/MeshCore-Beacon/beacon-server.git
synced 2026-11-04 14:27:20 +00:00
* Read each observer's receptions on their own in the observer comparison * Tighten the observer comparison plan checks
94 lines
3.1 KiB
Go
94 lines
3.1 KiB
Go
// Code generated by sqlc. DO NOT EDIT.
|
|
// versions:
|
|
// sqlc v1.31.1
|
|
// source: observer_comparison.sql
|
|
|
|
package db
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/jackc/pgx/v5/pgtype"
|
|
)
|
|
|
|
const getObserverComparison = `-- name: GetObserverComparison :one
|
|
WITH a AS (
|
|
SELECT po.packet_hash
|
|
FROM packet_observations po
|
|
WHERE po.observer_id = (SELECT $1::uuid)
|
|
AND po.heard_at >= $3::timestamptz
|
|
AND po.heard_at < $4::timestamptz
|
|
AND (COALESCE(cardinality($5::text[]), 0) = 0 OR po.iata = ANY($5::text[]))
|
|
), b AS (
|
|
SELECT po.packet_hash
|
|
FROM packet_observations po
|
|
WHERE po.observer_id = (SELECT $2::uuid)
|
|
AND po.heard_at >= $3::timestamptz
|
|
AND po.heard_at < $4::timestamptz
|
|
AND (COALESCE(cardinality($5::text[]), 0) = 0 OR po.iata = ANY($5::text[]))
|
|
), heard AS (
|
|
SELECT COALESCE(a.packet_hash, b.packet_hash) AS packet_hash,
|
|
a.packet_hash IS NOT NULL AS seen_a,
|
|
b.packet_hash IS NOT NULL AS seen_b
|
|
FROM a FULL JOIN b ON b.packet_hash = a.packet_hash
|
|
)
|
|
SELECT count(*) AS total_packets,
|
|
count(*) FILTER (WHERE seen_a AND NOT seen_b) AS only_a,
|
|
count(*) FILTER (WHERE seen_b AND NOT seen_a) AS only_b,
|
|
count(*) FILTER (WHERE seen_a AND seen_b) AS both,
|
|
EXISTS (SELECT 1 FROM observers WHERE id = $1::uuid) AS known_a,
|
|
EXISTS (SELECT 1 FROM observers WHERE id = $2::uuid) AS known_b
|
|
FROM heard
|
|
JOIN packets p ON p.packet_hash = heard.packet_hash
|
|
WHERE p.route_type IN (0, 1)
|
|
`
|
|
|
|
type GetObserverComparisonParams struct {
|
|
ObserverA uuid.UUID `json:"observer_a"`
|
|
ObserverB uuid.UUID `json:"observer_b"`
|
|
Since pgtype.Timestamptz `json:"since"`
|
|
Until pgtype.Timestamptz `json:"until"`
|
|
Iatas []string `json:"iatas"`
|
|
}
|
|
|
|
type GetObserverComparisonRow struct {
|
|
TotalPackets int64 `json:"total_packets"`
|
|
OnlyA int64 `json:"only_a"`
|
|
OnlyB int64 `json:"only_b"`
|
|
Both int64 `json:"both"`
|
|
KnownA bool `json:"known_a"`
|
|
KnownB bool `json:"known_b"`
|
|
}
|
|
|
|
// Count packet identities, not reception rows: a broker repeat or another
|
|
// reception by the same observer must not inflate the comparison.
|
|
//
|
|
// Each observer's receptions are read on their own from idx_observations_observer
|
|
// (observer_id, heard_at): (packet_hash, observer_id) is unique, so each side
|
|
// holds a packet at most once, and the full join yields each heard packet once.
|
|
// The route type is checked once per packet after the join.
|
|
// The observer ids are scalar subqueries so the planner costs every observer
|
|
// alike: given a busy observer's own row count, a custom plan may instead walk
|
|
// every reception in the window through idx_observations_heard, which reads
|
|
// several times the buffers.
|
|
func (q *Queries) GetObserverComparison(ctx context.Context, arg GetObserverComparisonParams) (GetObserverComparisonRow, error) {
|
|
row := q.db.QueryRow(ctx, getObserverComparison,
|
|
arg.ObserverA,
|
|
arg.ObserverB,
|
|
arg.Since,
|
|
arg.Until,
|
|
arg.Iatas,
|
|
)
|
|
var i GetObserverComparisonRow
|
|
err := row.Scan(
|
|
&i.TotalPackets,
|
|
&i.OnlyA,
|
|
&i.OnlyB,
|
|
&i.Both,
|
|
&i.KnownA,
|
|
&i.KnownB,
|
|
)
|
|
return i, err
|
|
}
|