Files
beacon-server/db/sqlc/observer_comparison.sql.go
T
MrAlders0n 433ad0234a Observer comparison: read each observer's receptions on their own (#260)
* Read each observer's receptions on their own in the observer comparison

* Tighten the observer comparison plan checks
2026-10-20 18:47:08 -04:00

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
}