New tg ID schema and initial importer #35
15 changed files with 348 additions and 177 deletions
|
@ -229,10 +229,10 @@ func (as *alerter) scoredTGs() []talkgroups.ID {
|
||||||
}
|
}
|
||||||
|
|
||||||
// packedScoredTGs gets a list of packed TGIDs.
|
// packedScoredTGs gets a list of packed TGIDs.
|
||||||
func (as *alerter) packedScoredTGs() []int64 {
|
func (as *alerter) scoredTGsTuple() []database.TalkgroupT {
|
||||||
tgs := make([]int64, 0, len(as.scores))
|
tgs := make([]database.TalkgroupT, 0, len(as.scores))
|
||||||
for _, s := range as.scores {
|
for _, s := range as.scores {
|
||||||
tgs = append(tgs, s.ID.Pack())
|
tgs = append(tgs, s.ID.Tuple())
|
||||||
}
|
}
|
||||||
|
|
||||||
return tgs
|
return tgs
|
||||||
|
|
|
@ -40,7 +40,7 @@ func (as *alerter) tgStatsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
db := database.FromCtx(ctx)
|
db := database.FromCtx(ctx)
|
||||||
|
|
||||||
tgs, err := db.GetTalkgroupsWithLearnedByPackedIDs(ctx, as.packedScoredTGs())
|
tgs, err := db.GetTalkgroupsWithLearnedByPackedIDs(ctx, as.scoredTGsTuple())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("stats TG get failed")
|
log.Error().Err(err).Msg("stats TG get failed")
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
|
|
@ -83,7 +83,7 @@ type System struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Talkgroup struct {
|
type Talkgroup struct {
|
||||||
ID int64 `json:"id"`
|
ID uuid.UUID `json:"id"`
|
||||||
SystemID int32 `json:"system_id"`
|
SystemID int32 `json:"system_id"`
|
||||||
Tgid int32 `json:"tgid"`
|
Tgid int32 `json:"tgid"`
|
||||||
Name *string `json:"name"`
|
Name *string `json:"name"`
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
type Querier interface {
|
type Querier interface {
|
||||||
AddAlert(ctx context.Context, arg AddAlertParams) error
|
AddAlert(ctx context.Context, arg AddAlertParams) error
|
||||||
AddCall(ctx context.Context, arg AddCallParams) error
|
AddCall(ctx context.Context, arg AddCallParams) error
|
||||||
BulkSetTalkgroupTags(ctx context.Context, iD int64, tags []string) error
|
BulkSetTalkgroupTags(ctx context.Context, iD uuid.UUID, tags []string) error
|
||||||
CreateAPIKey(ctx context.Context, owner int, expires pgtype.Timestamp, disabled *bool) (ApiKey, error)
|
CreateAPIKey(ctx context.Context, owner int, expires pgtype.Timestamp, disabled *bool) (ApiKey, error)
|
||||||
CreateUser(ctx context.Context, arg CreateUserParams) (User, error)
|
CreateUser(ctx context.Context, arg CreateUserParams) (User, error)
|
||||||
DeleteAPIKey(ctx context.Context, apiKey string) error
|
DeleteAPIKey(ctx context.Context, apiKey string) error
|
||||||
|
@ -22,15 +22,13 @@ type Querier interface {
|
||||||
GetAPIKey(ctx context.Context, apiKey string) (ApiKey, error)
|
GetAPIKey(ctx context.Context, apiKey string) (ApiKey, error)
|
||||||
GetDatabaseSize(ctx context.Context) (string, error)
|
GetDatabaseSize(ctx context.Context) (string, error)
|
||||||
GetSystemName(ctx context.Context, systemID int) (string, error)
|
GetSystemName(ctx context.Context, systemID int) (string, error)
|
||||||
GetTalkgroup(ctx context.Context, systemID int, tgid int) (GetTalkgroupRow, error)
|
GetTalkgroup(ctx context.Context, systemID int32, tgid int32) (GetTalkgroupRow, error)
|
||||||
GetTalkgroupIDsByTags(ctx context.Context, anytags []string, alltags []string, nottags []string) ([]GetTalkgroupIDsByTagsRow, error)
|
GetTalkgroupIDsByTags(ctx context.Context, anytags []string, alltags []string, nottags []string) ([]GetTalkgroupIDsByTagsRow, error)
|
||||||
GetTalkgroupTags(ctx context.Context, sys int, tg int) ([]string, error)
|
GetTalkgroupTags(ctx context.Context, sys int, tg int) ([]string, error)
|
||||||
GetTalkgroupWithLearned(ctx context.Context, systemID int, tgid int) (GetTalkgroupWithLearnedRow, error)
|
GetTalkgroupWithLearned(ctx context.Context, systemID int32, tgid int32) (GetTalkgroupWithLearnedRow, error)
|
||||||
GetTalkgroupsByPackedIDs(ctx context.Context, dollar_1 []int64) ([]GetTalkgroupsByPackedIDsRow, error)
|
|
||||||
GetTalkgroupsWithAllTags(ctx context.Context, tags []string) ([]GetTalkgroupsWithAllTagsRow, error)
|
GetTalkgroupsWithAllTags(ctx context.Context, tags []string) ([]GetTalkgroupsWithAllTagsRow, error)
|
||||||
GetTalkgroupsWithAnyTags(ctx context.Context, tags []string) ([]GetTalkgroupsWithAnyTagsRow, error)
|
GetTalkgroupsWithAnyTags(ctx context.Context, tags []string) ([]GetTalkgroupsWithAnyTagsRow, error)
|
||||||
GetTalkgroupsWithLearned(ctx context.Context) ([]GetTalkgroupsWithLearnedRow, error)
|
GetTalkgroupsWithLearned(ctx context.Context) ([]GetTalkgroupsWithLearnedRow, error)
|
||||||
GetTalkgroupsWithLearnedByPackedIDs(ctx context.Context, dollar_1 []int64) ([]GetTalkgroupsWithLearnedByPackedIDsRow, error)
|
|
||||||
GetTalkgroupsWithLearnedBySystem(ctx context.Context, system int32) ([]GetTalkgroupsWithLearnedBySystemRow, error)
|
GetTalkgroupsWithLearnedBySystem(ctx context.Context, system int32) ([]GetTalkgroupsWithLearnedBySystemRow, error)
|
||||||
GetUserByID(ctx context.Context, id int32) (User, error)
|
GetUserByID(ctx context.Context, id int32) (User, error)
|
||||||
GetUserByUID(ctx context.Context, id int32) (User, error)
|
GetUserByUID(ctx context.Context, id int32) (User, error)
|
||||||
|
|
124
pkg/database/talkgroups.manual.sql.go
Normal file
124
pkg/database/talkgroups.manual.sql.go
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql/driver"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TalkgroupT struct {
|
||||||
|
System uint32 `json:"sys"`
|
||||||
|
Talkgroup uint32 `json:"tg"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t TalkgroupT) Value() (driver.Value, error) {
|
||||||
|
return [2]uint32{t.System, t.Talkgroup}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const getTalkgroupsWithLearnedByPackedIDs = `-- name: GetTalkgroupsWithLearnedByPackedIDs :many
|
||||||
|
SELECT
|
||||||
|
tg.id, tg.system_id, tg.tgid, tg.name, tg.alpha_tag, tg.tg_group, tg.frequency, tg.metadata, tg.tags, tg.alert, tg.alert_config, tg.weight, sys.id, sys.name,
|
||||||
|
FALSE learned
|
||||||
|
FROM talkgroups tg
|
||||||
|
JOIN systems sys ON tg.system_id = sys.id
|
||||||
|
WHERE (tg.system_id, tg.tgid) = ANY($1)
|
||||||
|
UNION
|
||||||
|
SELECT
|
||||||
|
NULL::UUID, tgl.system_id::INT4, tgl.tgid::INT4, tgl.name,
|
||||||
|
tgl.alpha_tag, tgl.alpha_tag, NULL::INTEGER, NULL::JSONB,
|
||||||
|
CASE WHEN tgl.alpha_tag IS NULL THEN NULL ELSE ARRAY[tgl.alpha_tag] END,
|
||||||
|
TRUE, NULL::JSONB, 1.0, sys.id, sys.name,
|
||||||
|
TRUE learned
|
||||||
|
FROM talkgroups_learned tgl
|
||||||
|
JOIN systems sys ON tgl.system_id = sys.id
|
||||||
|
WHERE (tgl.system_id, tgl.tgid) = ANY($1);
|
||||||
|
`
|
||||||
|
|
||||||
|
type GetTalkgroupsWithLearnedByPackedIDsRow struct {
|
||||||
|
Talkgroup Talkgroup `json:"talkgroup"`
|
||||||
|
System System `json:"system"`
|
||||||
|
Learned bool `json:"learned"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) GetTalkgroupsWithLearnedByPackedIDs(ctx context.Context, ids []TalkgroupT) ([]GetTalkgroupsWithLearnedByPackedIDsRow, error) {
|
||||||
|
rows, err := q.db.Query(ctx, getTalkgroupsWithLearnedByPackedIDs, ids)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
var items []GetTalkgroupsWithLearnedByPackedIDsRow
|
||||||
|
for rows.Next() {
|
||||||
|
var i GetTalkgroupsWithLearnedByPackedIDsRow
|
||||||
|
if err := rows.Scan(
|
||||||
|
&i.Talkgroup.ID,
|
||||||
|
&i.Talkgroup.SystemID,
|
||||||
|
&i.Talkgroup.Tgid,
|
||||||
|
&i.Talkgroup.Name,
|
||||||
|
&i.Talkgroup.AlphaTag,
|
||||||
|
&i.Talkgroup.TgGroup,
|
||||||
|
&i.Talkgroup.Frequency,
|
||||||
|
&i.Talkgroup.Metadata,
|
||||||
|
&i.Talkgroup.Tags,
|
||||||
|
&i.Talkgroup.Alert,
|
||||||
|
&i.Talkgroup.AlertConfig,
|
||||||
|
&i.Talkgroup.Weight,
|
||||||
|
&i.System.ID,
|
||||||
|
&i.System.Name,
|
||||||
|
&i.Learned,
|
||||||
|
); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
items = append(items, i)
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const getTalkgroupsByPackedIDs = `-- name: GetTalkgroupsByPackedIDs :many
|
||||||
|
SELECT tg.id, tg.system_id, tg.tgid, tg.name, tg.alpha_tag, tg.tg_group, tg.frequency, tg.metadata, tg.tags, tg.alert, tg.alert_config, tg.weight, sys.id, sys.name FROM talkgroups tg
|
||||||
|
JOIN systems sys ON tg.system_id = sys.id
|
||||||
|
WHERE (tg.system_id, tg.tgid) = ANY($1)
|
||||||
|
`
|
||||||
|
|
||||||
|
type GetTalkgroupsByPackedIDsRow struct {
|
||||||
|
Talkgroup Talkgroup `json:"talkgroup"`
|
||||||
|
System System `json:"system"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) GetTalkgroupsByPackedIDs(ctx context.Context, idtuple []TalkgroupT) ([]GetTalkgroupsByPackedIDsRow, error) {
|
||||||
|
rows, err := q.db.Query(ctx, getTalkgroupsByPackedIDs, idtuple)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
var items []GetTalkgroupsByPackedIDsRow
|
||||||
|
for rows.Next() {
|
||||||
|
var i GetTalkgroupsByPackedIDsRow
|
||||||
|
if err := rows.Scan(
|
||||||
|
&i.Talkgroup.ID,
|
||||||
|
&i.Talkgroup.SystemID,
|
||||||
|
&i.Talkgroup.Tgid,
|
||||||
|
&i.Talkgroup.Name,
|
||||||
|
&i.Talkgroup.AlphaTag,
|
||||||
|
&i.Talkgroup.TgGroup,
|
||||||
|
&i.Talkgroup.Frequency,
|
||||||
|
&i.Talkgroup.Metadata,
|
||||||
|
&i.Talkgroup.Tags,
|
||||||
|
&i.Talkgroup.Alert,
|
||||||
|
&i.Talkgroup.AlertConfig,
|
||||||
|
&i.Talkgroup.Weight,
|
||||||
|
&i.System.ID,
|
||||||
|
&i.System.Name,
|
||||||
|
); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
items = append(items, i)
|
||||||
|
}
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@ import (
|
||||||
|
|
||||||
"dynatron.me/x/stillbox/internal/jsontypes"
|
"dynatron.me/x/stillbox/internal/jsontypes"
|
||||||
"dynatron.me/x/stillbox/pkg/alerting/rules"
|
"dynatron.me/x/stillbox/pkg/alerting/rules"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/jackc/pgx/v5/pgtype"
|
||||||
)
|
)
|
||||||
|
|
||||||
const bulkSetTalkgroupTags = `-- name: BulkSetTalkgroupTags :exec
|
const bulkSetTalkgroupTags = `-- name: BulkSetTalkgroupTags :exec
|
||||||
|
@ -17,7 +19,7 @@ UPDATE talkgroups SET tags = $2
|
||||||
WHERE id = ANY($1)
|
WHERE id = ANY($1)
|
||||||
`
|
`
|
||||||
|
|
||||||
func (q *Queries) BulkSetTalkgroupTags(ctx context.Context, iD int64, tags []string) error {
|
func (q *Queries) BulkSetTalkgroupTags(ctx context.Context, iD uuid.UUID, tags []string) error {
|
||||||
_, err := q.db.Exec(ctx, bulkSetTalkgroupTags, iD, tags)
|
_, err := q.db.Exec(ctx, bulkSetTalkgroupTags, iD, tags)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -35,14 +37,14 @@ func (q *Queries) GetSystemName(ctx context.Context, systemID int) (string, erro
|
||||||
|
|
||||||
const getTalkgroup = `-- name: GetTalkgroup :one
|
const getTalkgroup = `-- name: GetTalkgroup :one
|
||||||
SELECT talkgroups.id, talkgroups.system_id, talkgroups.tgid, talkgroups.name, talkgroups.alpha_tag, talkgroups.tg_group, talkgroups.frequency, talkgroups.metadata, talkgroups.tags, talkgroups.alert, talkgroups.alert_config, talkgroups.weight FROM talkgroups
|
SELECT talkgroups.id, talkgroups.system_id, talkgroups.tgid, talkgroups.name, talkgroups.alpha_tag, talkgroups.tg_group, talkgroups.frequency, talkgroups.metadata, talkgroups.tags, talkgroups.alert, talkgroups.alert_config, talkgroups.weight FROM talkgroups
|
||||||
WHERE id = systg2id($1, $2)
|
WHERE (system_id, tgid) = ($1, $2)
|
||||||
`
|
`
|
||||||
|
|
||||||
type GetTalkgroupRow struct {
|
type GetTalkgroupRow struct {
|
||||||
Talkgroup Talkgroup `json:"talkgroup"`
|
Talkgroup Talkgroup `json:"talkgroup"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) GetTalkgroup(ctx context.Context, systemID int, tgid int) (GetTalkgroupRow, error) {
|
func (q *Queries) GetTalkgroup(ctx context.Context, systemID int32, tgid int32) (GetTalkgroupRow, error) {
|
||||||
row := q.db.QueryRow(ctx, getTalkgroup, systemID, tgid)
|
row := q.db.QueryRow(ctx, getTalkgroup, systemID, tgid)
|
||||||
var i GetTalkgroupRow
|
var i GetTalkgroupRow
|
||||||
err := row.Scan(
|
err := row.Scan(
|
||||||
|
@ -112,7 +114,7 @@ tg.id, tg.system_id, tg.tgid, tg.name, tg.alpha_tag, tg.tg_group, tg.frequency,
|
||||||
FALSE learned
|
FALSE learned
|
||||||
FROM talkgroups tg
|
FROM talkgroups tg
|
||||||
JOIN systems sys ON tg.system_id = sys.id
|
JOIN systems sys ON tg.system_id = sys.id
|
||||||
WHERE tg.id = systg2id($1, $2)
|
WHERE (tg.system_id, tg.tgid) = ($1, $2)
|
||||||
UNION
|
UNION
|
||||||
SELECT
|
SELECT
|
||||||
tgl.id::INT8, tgl.system_id::INT4, tgl.tgid::INT4, tgl.name,
|
tgl.id::INT8, tgl.system_id::INT4, tgl.tgid::INT4, tgl.name,
|
||||||
|
@ -131,7 +133,7 @@ type GetTalkgroupWithLearnedRow struct {
|
||||||
Learned bool `json:"learned"`
|
Learned bool `json:"learned"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) GetTalkgroupWithLearned(ctx context.Context, systemID int, tgid int) (GetTalkgroupWithLearnedRow, error) {
|
func (q *Queries) GetTalkgroupWithLearned(ctx context.Context, systemID int32, tgid int32) (GetTalkgroupWithLearnedRow, error) {
|
||||||
row := q.db.QueryRow(ctx, getTalkgroupWithLearned, systemID, tgid)
|
row := q.db.QueryRow(ctx, getTalkgroupWithLearned, systemID, tgid)
|
||||||
var i GetTalkgroupWithLearnedRow
|
var i GetTalkgroupWithLearnedRow
|
||||||
err := row.Scan(
|
err := row.Scan(
|
||||||
|
@ -154,52 +156,6 @@ func (q *Queries) GetTalkgroupWithLearned(ctx context.Context, systemID int, tgi
|
||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTalkgroupsByPackedIDs = `-- name: GetTalkgroupsByPackedIDs :many
|
|
||||||
SELECT tg.id, tg.system_id, tg.tgid, tg.name, tg.alpha_tag, tg.tg_group, tg.frequency, tg.metadata, tg.tags, tg.alert, tg.alert_config, tg.weight, sys.id, sys.name FROM talkgroups tg
|
|
||||||
JOIN systems sys ON tg.system_id = sys.id
|
|
||||||
WHERE tg.id = ANY($1::INT8[])
|
|
||||||
`
|
|
||||||
|
|
||||||
type GetTalkgroupsByPackedIDsRow struct {
|
|
||||||
Talkgroup Talkgroup `json:"talkgroup"`
|
|
||||||
System System `json:"system"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *Queries) GetTalkgroupsByPackedIDs(ctx context.Context, dollar_1 []int64) ([]GetTalkgroupsByPackedIDsRow, error) {
|
|
||||||
rows, err := q.db.Query(ctx, getTalkgroupsByPackedIDs, dollar_1)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
var items []GetTalkgroupsByPackedIDsRow
|
|
||||||
for rows.Next() {
|
|
||||||
var i GetTalkgroupsByPackedIDsRow
|
|
||||||
if err := rows.Scan(
|
|
||||||
&i.Talkgroup.ID,
|
|
||||||
&i.Talkgroup.SystemID,
|
|
||||||
&i.Talkgroup.Tgid,
|
|
||||||
&i.Talkgroup.Name,
|
|
||||||
&i.Talkgroup.AlphaTag,
|
|
||||||
&i.Talkgroup.TgGroup,
|
|
||||||
&i.Talkgroup.Frequency,
|
|
||||||
&i.Talkgroup.Metadata,
|
|
||||||
&i.Talkgroup.Tags,
|
|
||||||
&i.Talkgroup.Alert,
|
|
||||||
&i.Talkgroup.AlertConfig,
|
|
||||||
&i.Talkgroup.Weight,
|
|
||||||
&i.System.ID,
|
|
||||||
&i.System.Name,
|
|
||||||
); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
items = append(items, i)
|
|
||||||
}
|
|
||||||
if err := rows.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return items, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
const getTalkgroupsWithAllTags = `-- name: GetTalkgroupsWithAllTags :many
|
const getTalkgroupsWithAllTags = `-- name: GetTalkgroupsWithAllTags :many
|
||||||
SELECT talkgroups.id, talkgroups.system_id, talkgroups.tgid, talkgroups.name, talkgroups.alpha_tag, talkgroups.tg_group, talkgroups.frequency, talkgroups.metadata, talkgroups.tags, talkgroups.alert, talkgroups.alert_config, talkgroups.weight FROM talkgroups
|
SELECT talkgroups.id, talkgroups.system_id, talkgroups.tgid, talkgroups.name, talkgroups.alpha_tag, talkgroups.tg_group, talkgroups.frequency, talkgroups.metadata, talkgroups.tags, talkgroups.alert, talkgroups.alert_config, talkgroups.weight FROM talkgroups
|
||||||
WHERE tags && ARRAY[$1]
|
WHERE tags && ARRAY[$1]
|
||||||
|
@ -292,7 +248,7 @@ FROM talkgroups tg
|
||||||
JOIN systems sys ON tg.system_id = sys.id
|
JOIN systems sys ON tg.system_id = sys.id
|
||||||
UNION
|
UNION
|
||||||
SELECT
|
SELECT
|
||||||
tgl.id::INT8, tgl.system_id::INT4, tgl.tgid::INT4, tgl.name,
|
NULL::UUID, tgl.system_id::INT4, tgl.tgid::INT4, tgl.name,
|
||||||
tgl.alpha_tag, tgl.alpha_tag, NULL::INTEGER, NULL::JSONB,
|
tgl.alpha_tag, tgl.alpha_tag, NULL::INTEGER, NULL::JSONB,
|
||||||
CASE WHEN tgl.alpha_tag IS NULL THEN NULL ELSE ARRAY[tgl.alpha_tag] END,
|
CASE WHEN tgl.alpha_tag IS NULL THEN NULL ELSE ARRAY[tgl.alpha_tag] END,
|
||||||
TRUE, NULL::JSONB, 1.0, sys.id, sys.name,
|
TRUE, NULL::JSONB, 1.0, sys.id, sys.name,
|
||||||
|
@ -344,67 +300,6 @@ func (q *Queries) GetTalkgroupsWithLearned(ctx context.Context) ([]GetTalkgroups
|
||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTalkgroupsWithLearnedByPackedIDs = `-- name: GetTalkgroupsWithLearnedByPackedIDs :many
|
|
||||||
SELECT
|
|
||||||
tg.id, tg.system_id, tg.tgid, tg.name, tg.alpha_tag, tg.tg_group, tg.frequency, tg.metadata, tg.tags, tg.alert, tg.alert_config, tg.weight, sys.id, sys.name,
|
|
||||||
FALSE learned
|
|
||||||
FROM talkgroups tg
|
|
||||||
JOIN systems sys ON tg.system_id = sys.id
|
|
||||||
WHERE tg.id = ANY($1::INT8[])
|
|
||||||
UNION
|
|
||||||
SELECT
|
|
||||||
tgl.id::INT8, tgl.system_id::INT4, tgl.tgid::INT4, tgl.name,
|
|
||||||
tgl.alpha_tag, tgl.alpha_tag, NULL::INTEGER, NULL::JSONB,
|
|
||||||
CASE WHEN tgl.alpha_tag IS NULL THEN NULL ELSE ARRAY[tgl.alpha_tag] END,
|
|
||||||
TRUE, NULL::JSONB, 1.0, sys.id, sys.name,
|
|
||||||
TRUE learned
|
|
||||||
FROM talkgroups_learned tgl
|
|
||||||
JOIN systems sys ON tgl.system_id = sys.id
|
|
||||||
WHERE systg2id(tgl.system_id, tgl.tgid) = ANY($1::INT8[]) AND ignored IS NOT TRUE
|
|
||||||
`
|
|
||||||
|
|
||||||
type GetTalkgroupsWithLearnedByPackedIDsRow struct {
|
|
||||||
Talkgroup Talkgroup `json:"talkgroup"`
|
|
||||||
System System `json:"system"`
|
|
||||||
Learned bool `json:"learned"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *Queries) GetTalkgroupsWithLearnedByPackedIDs(ctx context.Context, dollar_1 []int64) ([]GetTalkgroupsWithLearnedByPackedIDsRow, error) {
|
|
||||||
rows, err := q.db.Query(ctx, getTalkgroupsWithLearnedByPackedIDs, dollar_1)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
var items []GetTalkgroupsWithLearnedByPackedIDsRow
|
|
||||||
for rows.Next() {
|
|
||||||
var i GetTalkgroupsWithLearnedByPackedIDsRow
|
|
||||||
if err := rows.Scan(
|
|
||||||
&i.Talkgroup.ID,
|
|
||||||
&i.Talkgroup.SystemID,
|
|
||||||
&i.Talkgroup.Tgid,
|
|
||||||
&i.Talkgroup.Name,
|
|
||||||
&i.Talkgroup.AlphaTag,
|
|
||||||
&i.Talkgroup.TgGroup,
|
|
||||||
&i.Talkgroup.Frequency,
|
|
||||||
&i.Talkgroup.Metadata,
|
|
||||||
&i.Talkgroup.Tags,
|
|
||||||
&i.Talkgroup.Alert,
|
|
||||||
&i.Talkgroup.AlertConfig,
|
|
||||||
&i.Talkgroup.Weight,
|
|
||||||
&i.System.ID,
|
|
||||||
&i.System.Name,
|
|
||||||
&i.Learned,
|
|
||||||
); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
items = append(items, i)
|
|
||||||
}
|
|
||||||
if err := rows.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return items, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
const getTalkgroupsWithLearnedBySystem = `-- name: GetTalkgroupsWithLearnedBySystem :many
|
const getTalkgroupsWithLearnedBySystem = `-- name: GetTalkgroupsWithLearnedBySystem :many
|
||||||
SELECT
|
SELECT
|
||||||
tg.id, tg.system_id, tg.tgid, tg.name, tg.alpha_tag, tg.tg_group, tg.frequency, tg.metadata, tg.tags, tg.alert, tg.alert_config, tg.weight, sys.id, sys.name,
|
tg.id, tg.system_id, tg.tgid, tg.name, tg.alpha_tag, tg.tg_group, tg.frequency, tg.metadata, tg.tags, tg.alert, tg.alert_config, tg.weight, sys.id, sys.name,
|
||||||
|
@ -414,7 +309,7 @@ JOIN systems sys ON tg.system_id = sys.id
|
||||||
WHERE tg.system_id = $1
|
WHERE tg.system_id = $1
|
||||||
UNION
|
UNION
|
||||||
SELECT
|
SELECT
|
||||||
tgl.id::INT8, tgl.system_id::INT4, tgl.tgid::INT4, tgl.name,
|
NULL::UUID, tgl.system_id::INT4, tgl.tgid::INT4, tgl.name,
|
||||||
tgl.alpha_tag, tgl.alpha_tag, NULL::INTEGER, NULL::JSONB,
|
tgl.alpha_tag, tgl.alpha_tag, NULL::INTEGER, NULL::JSONB,
|
||||||
CASE WHEN tgl.alpha_tag IS NULL THEN NULL ELSE ARRAY[tgl.alpha_tag] END,
|
CASE WHEN tgl.alpha_tag IS NULL THEN NULL ELSE ARRAY[tgl.alpha_tag] END,
|
||||||
TRUE, NULL::JSONB, 1.0, sys.id, sys.name,
|
TRUE, NULL::JSONB, 1.0, sys.id, sys.name,
|
||||||
|
@ -488,7 +383,7 @@ SET
|
||||||
alert = COALESCE($7, alert),
|
alert = COALESCE($7, alert),
|
||||||
alert_config = COALESCE($8, alert_config),
|
alert_config = COALESCE($8, alert_config),
|
||||||
weight = COALESCE($9, weight)
|
weight = COALESCE($9, weight)
|
||||||
WHERE id = $10
|
WHERE id = $10 OR (system_id = $11 AND tgid = $12)
|
||||||
RETURNING id, system_id, tgid, name, alpha_tag, tg_group, frequency, metadata, tags, alert, alert_config, weight
|
RETURNING id, system_id, tgid, name, alpha_tag, tg_group, frequency, metadata, tags, alert, alert_config, weight
|
||||||
`
|
`
|
||||||
|
|
||||||
|
@ -502,7 +397,9 @@ type UpdateTalkgroupParams struct {
|
||||||
Alert *bool `json:"alert"`
|
Alert *bool `json:"alert"`
|
||||||
AlertConfig rules.AlertRules `json:"alert_config"`
|
AlertConfig rules.AlertRules `json:"alert_config"`
|
||||||
Weight *float32 `json:"weight"`
|
Weight *float32 `json:"weight"`
|
||||||
ID int64 `json:"id"`
|
ID pgtype.UUID `json:"id"`
|
||||||
|
SystemID *int32 `json:"system_id"`
|
||||||
|
Tgid *int32 `json:"tgid"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) UpdateTalkgroup(ctx context.Context, arg UpdateTalkgroupParams) (Talkgroup, error) {
|
func (q *Queries) UpdateTalkgroup(ctx context.Context, arg UpdateTalkgroupParams) (Talkgroup, error) {
|
||||||
|
@ -517,6 +414,8 @@ func (q *Queries) UpdateTalkgroup(ctx context.Context, arg UpdateTalkgroupParams
|
||||||
arg.AlertConfig,
|
arg.AlertConfig,
|
||||||
arg.Weight,
|
arg.Weight,
|
||||||
arg.ID,
|
arg.ID,
|
||||||
|
arg.SystemID,
|
||||||
|
arg.Tgid,
|
||||||
)
|
)
|
||||||
var i Talkgroup
|
var i Talkgroup
|
||||||
err := row.Scan(
|
err := row.Scan(
|
||||||
|
|
|
@ -97,7 +97,6 @@ func (tga *talkgroupAPI) put(w http.ResponseWriter, r *http.Request) {
|
||||||
wErr(w, r, badRequest(err))
|
wErr(w, r, badRequest(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
input.ID = id.ToID().Pack()
|
|
||||||
|
|
||||||
record, err := tgs.UpdateTG(ctx, input)
|
record, err := tgs.UpdateTG(ctx, input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -40,7 +40,7 @@ type Store interface {
|
||||||
Hint(ctx context.Context, tgs []ID) error
|
Hint(ctx context.Context, tgs []ID) error
|
||||||
|
|
||||||
// Load loads the provided packed talkgroup IDs into the Store.
|
// Load loads the provided packed talkgroup IDs into the Store.
|
||||||
Load(ctx context.Context, tgs []int64) error
|
Load(ctx context.Context, tgs []database.TalkgroupT) error
|
||||||
|
|
||||||
// Invalidate invalidates any caching in the Store.
|
// Invalidate invalidates any caching in the Store.
|
||||||
Invalidate()
|
Invalidate()
|
||||||
|
@ -98,19 +98,19 @@ func NewCache() Store {
|
||||||
|
|
||||||
func (t *cache) Hint(ctx context.Context, tgs []ID) error {
|
func (t *cache) Hint(ctx context.Context, tgs []ID) error {
|
||||||
t.RLock()
|
t.RLock()
|
||||||
var toLoad []int64
|
var toLoad []database.TalkgroupT
|
||||||
if len(t.tgs) > len(tgs)/2 { // TODO: instrument this
|
if len(t.tgs) > len(tgs)/2 { // TODO: instrument this
|
||||||
for _, tg := range tgs {
|
for _, tg := range tgs {
|
||||||
_, ok := t.tgs[tg]
|
_, ok := t.tgs[tg]
|
||||||
if !ok {
|
if !ok {
|
||||||
toLoad = append(toLoad, tg.Pack())
|
toLoad = append(toLoad, tg.Tuple())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
toLoad = make([]int64, 0, len(tgs))
|
toLoad = make([]database.TalkgroupT, 0, len(tgs))
|
||||||
for _, g := range tgs {
|
for _, g := range tgs {
|
||||||
toLoad = append(toLoad, g.Pack())
|
toLoad = append(toLoad, g.Tuple())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,7 +180,7 @@ func (t *cache) TGs(ctx context.Context, tgs IDs) ([]*Talkgroup, error) {
|
||||||
}
|
}
|
||||||
t.RUnlock()
|
t.RUnlock()
|
||||||
|
|
||||||
tgRecords, err := database.FromCtx(ctx).GetTalkgroupsWithLearnedByPackedIDs(ctx, toGet.Packed())
|
tgRecords, err := database.FromCtx(ctx).GetTalkgroupsWithLearnedByPackedIDs(ctx, toGet.Tuples())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -196,7 +196,7 @@ func (t *cache) TGs(ctx context.Context, tgs IDs) ([]*Talkgroup, error) {
|
||||||
return addToRowList(t, r, tgRecords)
|
return addToRowList(t, r, tgRecords)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *cache) Load(ctx context.Context, tgs []int64) error {
|
func (t *cache) Load(ctx context.Context, tgs []database.TalkgroupT) error {
|
||||||
tgRecords, err := database.FromCtx(ctx).GetTalkgroupsWithLearnedByPackedIDs(ctx, tgs)
|
tgRecords, err := database.FromCtx(ctx).GetTalkgroupsWithLearnedByPackedIDs(ctx, tgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -245,7 +245,7 @@ func (t *cache) TG(ctx context.Context, tg ID) (*Talkgroup, error) {
|
||||||
return rec, nil
|
return rec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
recs, err := database.FromCtx(ctx).GetTalkgroupsWithLearnedByPackedIDs(ctx, []int64{tg.Pack()})
|
recs, err := database.FromCtx(ctx).GetTalkgroupsWithLearnedByPackedIDs(ctx, []database.TalkgroupT{tg.Tuple()})
|
||||||
switch err {
|
switch err {
|
||||||
case nil:
|
case nil:
|
||||||
case pgx.ErrNoRows:
|
case pgx.ErrNoRows:
|
||||||
|
@ -290,7 +290,7 @@ func (t *cache) SystemName(ctx context.Context, id int) (name string, has bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *cache) UpdateTG(ctx context.Context, input database.UpdateTalkgroupParams) (*Talkgroup, error) {
|
func (t *cache) UpdateTG(ctx context.Context, input database.UpdateTalkgroupParams) (*Talkgroup, error) {
|
||||||
sysName, has := t.SystemName(ctx, int(Unpack(input.ID).System))
|
sysName, has := t.SystemName(ctx, int(*input.SystemID))
|
||||||
if !has {
|
if !has {
|
||||||
return nil, ErrNoSuchSystem
|
return nil, ErrNoSuchSystem
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
|
||||||
"dynatron.me/x/stillbox/internal/jsontypes"
|
"dynatron.me/x/stillbox/internal/jsontypes"
|
||||||
"dynatron.me/x/stillbox/pkg/database"
|
"dynatron.me/x/stillbox/pkg/database"
|
||||||
)
|
)
|
||||||
|
@ -116,7 +118,7 @@ func (rr *radioReferenceImporter) importTalkgroups(ctx context.Context, sys int,
|
||||||
gn := groupName // must take a copy
|
gn := groupName // must take a copy
|
||||||
tgs = append(tgs, Talkgroup{
|
tgs = append(tgs, Talkgroup{
|
||||||
Talkgroup: database.Talkgroup{
|
Talkgroup: database.Talkgroup{
|
||||||
ID: tgt.Pack(),
|
ID: uuid.New(),
|
||||||
Tgid: int32(tgt.Talkgroup),
|
Tgid: int32(tgt.Talkgroup),
|
||||||
SystemID: int32(tgt.System),
|
SystemID: int32(tgt.System),
|
||||||
Name: &fields[4],
|
Name: &fields[4],
|
||||||
|
|
|
@ -26,10 +26,10 @@ type ID struct {
|
||||||
|
|
||||||
type IDs []ID
|
type IDs []ID
|
||||||
|
|
||||||
func (ids *IDs) Packed() []int64 {
|
func (ids *IDs) Tuples() []database.TalkgroupT {
|
||||||
r := make([]int64, len(*ids))
|
r := make([]database.TalkgroupT, len(*ids))
|
||||||
for i := range *ids {
|
for i := range *ids {
|
||||||
r[i] = (*ids)[i].Pack()
|
r[i] = (*ids)[i].Tuple()
|
||||||
}
|
}
|
||||||
|
|
||||||
return r
|
return r
|
||||||
|
@ -46,15 +46,10 @@ func TG[T intId, U intId](sys T, tgid U) ID {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t ID) Pack() int64 {
|
func (t ID) Tuple() database.TalkgroupT {
|
||||||
// P25 system IDs are 12 bits, so we can fit them in a signed 8 byte int (int64, pg INT8)
|
return database.TalkgroupT{
|
||||||
return int64((int64(t.System) << 32) | int64(t.Talkgroup))
|
System: t.System,
|
||||||
}
|
Talkgroup: t.Talkgroup,
|
||||||
|
|
||||||
func Unpack(id int64) ID {
|
|
||||||
return ID{
|
|
||||||
System: uint32(id >> 32),
|
|
||||||
Talkgroup: uint32(id & 0xffffffff),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
9
sql/postgres/migrations/002_reid.down.sql
Normal file
9
sql/postgres/migrations/002_reid.down.sql
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
DROP INDEX IF EXISTS talkgroups_system_tgid_idx;
|
||||||
|
|
||||||
|
ALTER TABLE talkgroups ALTER COLUMN id SET DATA TYPE INT8 USING (systg2id(system_id, tgid));
|
||||||
|
|
||||||
|
ALTER TABLE talkgroups DROP COLUMN IF EXISTS tgid;
|
||||||
|
ALTER TABLE talkgroups ADD COLUMN IF NOT EXISTS tgid INT4 NOT NULL GENERATED ALWAYS AS (id & x'ffffffff'::BIGINT) STORED,
|
||||||
|
|
||||||
|
ALTER TABLE talkgroups DROP COLUMN IF EXISTS system_id;
|
||||||
|
ALTER TABLE talkgroups ADD COLUMN IF NOT EXISTS system_id INT4 REFERENCES systems(id) NOT NULL GENERATED ALWAYS AS (id >> 32) STORED;
|
7
sql/postgres/migrations/002_reid.up.sql
Normal file
7
sql/postgres/migrations/002_reid.up.sql
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
ALTER TABLE talkgroups ALTER COLUMN system_id DROP EXPRESSION;
|
||||||
|
|
||||||
|
ALTER TABLE talkgroups ALTER COLUMN tgid DROP EXPRESSION;
|
||||||
|
|
||||||
|
ALTER TABLE talkgroups ALTER COLUMN id SET DATA TYPE UUID USING (gen_random_uuid());
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS talkgroups_system_tgid_idx ON talkgroups (system_id, tgid);
|
157
sql/postgres/migrations/flattened_initial.sql
Normal file
157
sql/postgres/migrations/flattened_initial.sql
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
CREATE TABLE IF NOT EXISTS users(
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
username VARCHAR (255) UNIQUE NOT NULL,
|
||||||
|
password TEXT NOT NULL,
|
||||||
|
email TEXT NOT NULL,
|
||||||
|
is_admin BOOLEAN NOT NULL,
|
||||||
|
prefs JSONB
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS users_username_idx ON users(username);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS api_keys(
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
owner INTEGER REFERENCES users(id) NOT NULL,
|
||||||
|
created_at TIMESTAMP NOT NULL,
|
||||||
|
expires TIMESTAMP,
|
||||||
|
disabled BOOLEAN,
|
||||||
|
api_key TEXT UNIQUE NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS systems(
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION systg2id(_sys INTEGER, _tg INTEGER) RETURNS INT8 LANGUAGE plpgsql AS
|
||||||
|
$$
|
||||||
|
BEGIN
|
||||||
|
RETURN ((_sys::BIGINT << 32) | _tg);
|
||||||
|
END
|
||||||
|
$$;
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION tgfromid(_id INT8) RETURNS INTEGER LANGUAGE plpgsql AS
|
||||||
|
$$
|
||||||
|
BEGIN
|
||||||
|
RETURN (_id & x'ffffffff'::BIGINT);
|
||||||
|
END
|
||||||
|
$$;
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION sysfromid(_id INT8) RETURNS INTEGER LANGUAGE plpgsql AS
|
||||||
|
$$
|
||||||
|
BEGIN
|
||||||
|
RETURN (_id >> 32);
|
||||||
|
END
|
||||||
|
$$;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS talkgroups(
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
system_id INT4 REFERENCES systems(id) NOT NULL,
|
||||||
|
tgid INT4 NOT NULL,
|
||||||
|
name TEXT,
|
||||||
|
alpha_tag TEXT,
|
||||||
|
tg_group TEXT,
|
||||||
|
frequency INTEGER,
|
||||||
|
metadata JSONB,
|
||||||
|
tags TEXT[] NOT NULL DEFAULT '{}',
|
||||||
|
alert BOOLEAN NOT NULL DEFAULT 'true',
|
||||||
|
alert_config JSONB,
|
||||||
|
weight REAL NOT NULL DEFAULT 1.0
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX talkgroups_system_tgid_idx ON talkgroups (system_id, tgid);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS talkgroup_id_tags ON talkgroups USING GIN (tags);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS talkgroups_learned(
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
system_id INTEGER REFERENCES systems(id) NOT NULL,
|
||||||
|
tgid INTEGER NOT NULL,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
alpha_tag TEXT,
|
||||||
|
ignored BOOLEAN,
|
||||||
|
UNIQUE (system_id, tgid, name)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS alerts(
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
time TIMESTAMPTZ NOT NULL,
|
||||||
|
tgid INTEGER NOT NULL,
|
||||||
|
system_id INTEGER REFERENCES systems(id) NOT NULL,
|
||||||
|
weight REAL,
|
||||||
|
score REAL,
|
||||||
|
orig_score REAL,
|
||||||
|
notified BOOLEAN NOT NULL DEFAULT 'false',
|
||||||
|
metadata JSONB
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION learn_talkgroup()
|
||||||
|
RETURNS TRIGGER AS $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (
|
||||||
|
SELECT tg.system_id, tg.tgid, tg.name, tg.alpha_tag FROM talkgroups tg WHERE tg.system_id = NEW.system AND tg.tgid = NEW.talkgroup
|
||||||
|
UNION
|
||||||
|
SELECT tgl.system_id, tgl.tgid, tgl.name, tgl.alpha_tag FROM talkgroups_learned tgl WHERE tgl.system_id = NEW.system AND tgl.tgid = NEW.talkgroup
|
||||||
|
) THEN
|
||||||
|
INSERT INTO talkgroups_learned(system_id, tgid, name, alpha_tag) VALUES(
|
||||||
|
NEW.system, NEW.talkgroup, NEW.tg_label, NEW.tg_alpha_tag
|
||||||
|
) ON CONFLICT DO NOTHING;
|
||||||
|
END IF;
|
||||||
|
RETURN NEW;
|
||||||
|
END
|
||||||
|
$$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS calls(
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
submitter INTEGER REFERENCES api_keys(id) ON DELETE SET NULL,
|
||||||
|
system INTEGER NOT NULL,
|
||||||
|
talkgroup INTEGER NOT NULL,
|
||||||
|
call_date TIMESTAMPTZ NOT NULL,
|
||||||
|
audio_name TEXT,
|
||||||
|
audio_blob BYTEA,
|
||||||
|
duration INTEGER,
|
||||||
|
audio_type TEXT,
|
||||||
|
audio_url TEXT,
|
||||||
|
frequency INTEGER NOT NULL,
|
||||||
|
frequencies INTEGER[],
|
||||||
|
patches INTEGER[],
|
||||||
|
tg_label TEXT,
|
||||||
|
tg_alpha_tag TEXT,
|
||||||
|
tg_group TEXT,
|
||||||
|
source INTEGER NOT NULL,
|
||||||
|
transcript TEXT
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE OR REPLACE TRIGGER learn_tg AFTER INSERT ON calls
|
||||||
|
FOR EACH ROW EXECUTE FUNCTION learn_talkgroup();
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS calls_transcript_idx ON calls USING GIN (to_tsvector('english', transcript));
|
||||||
|
CREATE INDEX IF NOT EXISTS calls_call_date_tg_idx ON calls(system, talkgroup, call_date);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS settings(
|
||||||
|
name TEXT PRIMARY KEY,
|
||||||
|
updated_by INTEGER REFERENCES users(id),
|
||||||
|
value JSONB
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS incidents(
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
start_time TIMESTAMP,
|
||||||
|
end_time TIMESTAMP,
|
||||||
|
location JSONB,
|
||||||
|
metadata JSONB
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS incidents_name_description_idx ON incidents USING GIN (
|
||||||
|
(to_tsvector('english', name) || to_tsvector('english', coalesce(description, ''))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS incidents_calls(
|
||||||
|
incident_id UUID REFERENCES incidents(id) ON UPDATE CASCADE ON DELETE CASCADE,
|
||||||
|
call_id UUID REFERENCES calls(id) ON UPDATE CASCADE,
|
||||||
|
notes JSONB,
|
||||||
|
PRIMARY KEY (incident_id, call_id)
|
||||||
|
);
|
|
@ -26,12 +26,7 @@ WHERE id = ANY($1);
|
||||||
|
|
||||||
-- name: GetTalkgroup :one
|
-- name: GetTalkgroup :one
|
||||||
SELECT sqlc.embed(talkgroups) FROM talkgroups
|
SELECT sqlc.embed(talkgroups) FROM talkgroups
|
||||||
WHERE id = systg2id(sqlc.arg(system_id), sqlc.arg(tgid));
|
WHERE (system_id, tgid) = (@system_id, @tgid);
|
||||||
|
|
||||||
-- name: GetTalkgroupsByPackedIDs :many
|
|
||||||
SELECT sqlc.embed(tg), sqlc.embed(sys) FROM talkgroups tg
|
|
||||||
JOIN systems sys ON tg.system_id = sys.id
|
|
||||||
WHERE tg.id = ANY($1::INT8[]);
|
|
||||||
|
|
||||||
-- name: GetTalkgroupWithLearned :one
|
-- name: GetTalkgroupWithLearned :one
|
||||||
SELECT
|
SELECT
|
||||||
|
@ -39,7 +34,7 @@ sqlc.embed(tg), sqlc.embed(sys),
|
||||||
FALSE learned
|
FALSE learned
|
||||||
FROM talkgroups tg
|
FROM talkgroups tg
|
||||||
JOIN systems sys ON tg.system_id = sys.id
|
JOIN systems sys ON tg.system_id = sys.id
|
||||||
WHERE tg.id = systg2id(sqlc.arg(system_id), sqlc.arg(tgid))
|
WHERE (tg.system_id, tg.tgid) = (sqlc.arg(system_id), sqlc.arg(tgid))
|
||||||
UNION
|
UNION
|
||||||
SELECT
|
SELECT
|
||||||
tgl.id::INT8, tgl.system_id::INT4, tgl.tgid::INT4, tgl.name,
|
tgl.id::INT8, tgl.system_id::INT4, tgl.tgid::INT4, tgl.name,
|
||||||
|
@ -51,24 +46,6 @@ FROM talkgroups_learned tgl
|
||||||
JOIN systems sys ON tgl.system_id = sys.id
|
JOIN systems sys ON tgl.system_id = sys.id
|
||||||
WHERE tgl.system_id = sqlc.arg(system_id) AND tgl.tgid = sqlc.arg(tgid) AND ignored IS NOT TRUE;
|
WHERE tgl.system_id = sqlc.arg(system_id) AND tgl.tgid = sqlc.arg(tgid) AND ignored IS NOT TRUE;
|
||||||
|
|
||||||
-- name: GetTalkgroupsWithLearnedByPackedIDs :many
|
|
||||||
SELECT
|
|
||||||
sqlc.embed(tg), sqlc.embed(sys),
|
|
||||||
FALSE learned
|
|
||||||
FROM talkgroups tg
|
|
||||||
JOIN systems sys ON tg.system_id = sys.id
|
|
||||||
WHERE tg.id = ANY($1::INT8[])
|
|
||||||
UNION
|
|
||||||
SELECT
|
|
||||||
tgl.id::INT8, tgl.system_id::INT4, tgl.tgid::INT4, tgl.name,
|
|
||||||
tgl.alpha_tag, tgl.alpha_tag, NULL::INTEGER, NULL::JSONB,
|
|
||||||
CASE WHEN tgl.alpha_tag IS NULL THEN NULL ELSE ARRAY[tgl.alpha_tag] END,
|
|
||||||
TRUE, NULL::JSONB, 1.0, sys.id, sys.name,
|
|
||||||
TRUE learned
|
|
||||||
FROM talkgroups_learned tgl
|
|
||||||
JOIN systems sys ON tgl.system_id = sys.id
|
|
||||||
WHERE systg2id(tgl.system_id, tgl.tgid) = ANY($1::INT8[]) AND ignored IS NOT TRUE;
|
|
||||||
|
|
||||||
-- name: GetTalkgroupsWithLearnedBySystem :many
|
-- name: GetTalkgroupsWithLearnedBySystem :many
|
||||||
SELECT
|
SELECT
|
||||||
sqlc.embed(tg), sqlc.embed(sys),
|
sqlc.embed(tg), sqlc.embed(sys),
|
||||||
|
@ -78,7 +55,7 @@ JOIN systems sys ON tg.system_id = sys.id
|
||||||
WHERE tg.system_id = @system
|
WHERE tg.system_id = @system
|
||||||
UNION
|
UNION
|
||||||
SELECT
|
SELECT
|
||||||
tgl.id::INT8, tgl.system_id::INT4, tgl.tgid::INT4, tgl.name,
|
NULL::UUID, tgl.system_id::INT4, tgl.tgid::INT4, tgl.name,
|
||||||
tgl.alpha_tag, tgl.alpha_tag, NULL::INTEGER, NULL::JSONB,
|
tgl.alpha_tag, tgl.alpha_tag, NULL::INTEGER, NULL::JSONB,
|
||||||
CASE WHEN tgl.alpha_tag IS NULL THEN NULL ELSE ARRAY[tgl.alpha_tag] END,
|
CASE WHEN tgl.alpha_tag IS NULL THEN NULL ELSE ARRAY[tgl.alpha_tag] END,
|
||||||
TRUE, NULL::JSONB, 1.0, sys.id, sys.name,
|
TRUE, NULL::JSONB, 1.0, sys.id, sys.name,
|
||||||
|
@ -95,7 +72,7 @@ FROM talkgroups tg
|
||||||
JOIN systems sys ON tg.system_id = sys.id
|
JOIN systems sys ON tg.system_id = sys.id
|
||||||
UNION
|
UNION
|
||||||
SELECT
|
SELECT
|
||||||
tgl.id::INT8, tgl.system_id::INT4, tgl.tgid::INT4, tgl.name,
|
NULL::UUID, tgl.system_id::INT4, tgl.tgid::INT4, tgl.name,
|
||||||
tgl.alpha_tag, tgl.alpha_tag, NULL::INTEGER, NULL::JSONB,
|
tgl.alpha_tag, tgl.alpha_tag, NULL::INTEGER, NULL::JSONB,
|
||||||
CASE WHEN tgl.alpha_tag IS NULL THEN NULL ELSE ARRAY[tgl.alpha_tag] END,
|
CASE WHEN tgl.alpha_tag IS NULL THEN NULL ELSE ARRAY[tgl.alpha_tag] END,
|
||||||
TRUE, NULL::JSONB, 1.0, sys.id, sys.name,
|
TRUE, NULL::JSONB, 1.0, sys.id, sys.name,
|
||||||
|
@ -119,5 +96,5 @@ SET
|
||||||
alert = COALESCE(sqlc.narg('alert'), alert),
|
alert = COALESCE(sqlc.narg('alert'), alert),
|
||||||
alert_config = COALESCE(sqlc.narg('alert_config'), alert_config),
|
alert_config = COALESCE(sqlc.narg('alert_config'), alert_config),
|
||||||
weight = COALESCE(sqlc.narg('weight'), weight)
|
weight = COALESCE(sqlc.narg('weight'), weight)
|
||||||
WHERE id = @id
|
WHERE id = sqlc.narg('id') OR (system_id = sqlc.narg('system_id') AND tgid = sqlc.narg('tgid'))
|
||||||
RETURNING *;
|
RETURNING *;
|
||||||
|
|
|
@ -37,3 +37,7 @@ sql:
|
||||||
import: "dynatron.me/x/stillbox/internal/jsontypes"
|
import: "dynatron.me/x/stillbox/internal/jsontypes"
|
||||||
type: "Metadata"
|
type: "Metadata"
|
||||||
nullable: true
|
nullable: true
|
||||||
|
- column: "(talkgroups.system_id, talkgroups.tgid)"
|
||||||
|
go_type:
|
||||||
|
import: "dynatron.me/x/stillbox/pkg/talkgroups"
|
||||||
|
type: "ID"
|
||||||
|
|
Loading…
Reference in a new issue