Added a new sync that uses hash

Added a new sync that uses hash and sqlc for the queries. Added db
migration. Started adding a config file.
This commit is contained in:
2024-12-19 12:11:20 +01:00
parent 8fa93d580d
commit 5ab19e16e5
26 changed files with 1527 additions and 45 deletions

View File

@@ -0,0 +1,4 @@
DROP TABLE game;
DROP TABLE song;
DROP TABLE song_list;
DROP TABLE vgmq;

View File

@@ -0,0 +1,43 @@
CREATE TABLE game (
id serial4 NOT NULL,
game_name varchar NOT NULL,
added timestamp NOT NULL,
deleted timestamp NULL,
last_changed timestamp NULL,
"path" varchar NOT NULL,
times_played int4 DEFAULT 0 NULL,
last_played timestamp NULL,
number_of_songs int4 NULL,
hash varchar NULL,
CONSTRAINT game_pkey PRIMARY KEY (id)
);
CREATE TABLE song (
game_id int4 NOT NULL,
song_name varchar NOT NULL,
"path" varchar NOT NULL,
times_played int4 DEFAULT 0 NULL,
hash varchar NULL,
file_name varchar NULL,
CONSTRAINT song_pkey PRIMARY KEY (game_id, path)
);
CREATE TABLE vgmq (
song_no int4 NOT NULL,
"path" varchar(50) NULL,
clue varchar(200) NULL,
answered bool DEFAULT false NOT NULL,
answer varchar(50) NULL,
CONSTRAINT vgmq_pk PRIMARY KEY (song_no)
);
CREATE UNIQUE INDEX vgmq_song_no_uindex ON vgmq USING btree (song_no);
CREATE TABLE song_list (
match_date date NOT NULL,
match_id int4 NOT NULL,
song_no int4 NOT NULL,
game_name varchar(50) NULL,
song_name varchar(50) NULL,
CONSTRAINT song_list_pkey PRIMARY KEY (match_date, match_id, song_no)
);
CREATE INDEX song_list_game_name_idx ON song_list USING btree (game_name);

View File

@@ -0,0 +1,3 @@
Alter table game
alter column number_of_songs set null,
alter column hash set null;

View File

@@ -0,0 +1,19 @@
BEGIN;
UPDATE game
SET number_of_songs = 0
WHERE number_of_songs IS NULL;
UPDATE game
SET hash = ''
WHERE hash IS NULL;
UPDATE song
SET hash = ''
WHERE hash IS NULL;
COMMIT;
BEGIN;
Alter table game
alter column number_of_songs set not null,
alter column number_of_songs set default 0,
ALTER COLUMN hash SET NOT NULL;
ALTER TABLE song
ALTER COLUMN hash SET NOT NULL;
COMMIT;

49
db/queries/game.sql Normal file
View File

@@ -0,0 +1,49 @@
-- name: ResetGameIdSeq :one
SELECT setval('game_id_seq', (SELECT MAX(id) FROM game)+1);
-- name: GetGameNameById :one
SELECT game_name FROM game WHERE id = $1;
-- name: GetGameById :one
SELECT *
FROM game
WHERE id = $1
AND deleted IS NULL;
-- name: SetGameDeletionDate :exec
UPDATE game SET deleted=now() WHERE deleted IS NULL;
-- name: ClearGames :exec
DELETE FROM game;
-- name: UpdateGameName :exec
UPDATE game SET game_name=sqlc.arg(name), path=sqlc.arg(path), last_changed=now() WHERE id=sqlc.arg(id);
-- name: UpdateGameHash :exec
UPDATE game SET hash=sqlc.arg(hash), last_changed=now() WHERE id=sqlc.arg(id);
-- name: RemoveDeletionDate :exec
UPDATE game SET deleted=NULL WHERE id=$1;
-- name: GetIdByGameName :one
SELECT id FROM game WHERE game_name = $1;
-- name: InsertGame :one
INSERT INTO game (game_name, path, hash, added) VALUES ($1, $2, $3, now()) returning id;
-- name: InsertGameWithExistingId :exec
INSERT INTO game (id, game_name, path, hash, added) VALUES ($1, $2, $3, $4, now());
-- name: FindAllGames :many
SELECT *
FROM game
WHERE deleted IS NULL
ORDER BY game_name;
-- name: GetAllGamesIncludingDeleted :many
SELECT *
FROM game
ORDER BY game_name;
-- name: AddGamePlayed :exec
UPDATE game SET times_played = times_played + 1, last_played = now() WHERE id = $1;

41
db/queries/song.sql Normal file
View File

@@ -0,0 +1,41 @@
-- name: ClearSongs :exec
DELETE FROM song;
-- name: ClearSongsByGameId :exec
DELETE FROM song WHERE game_id = $1;
-- name: AddSong :exec
INSERT INTO song(game_id, song_name, path, file_name, hash) VALUES ($1, $2, $3, $4, $5);
-- name: CheckSong :one
SELECT COUNT(*) FROM song WHERE path = $1;
-- name: CheckSongWithHash :one
SELECT COUNT(*) FROM song WHERE hash = $1;
-- name: GetSongWithHash :one
SELECT * FROM song WHERE hash = $1;
-- name: UpdateSong :exec
UPDATE song SET song_name=$1, file_name=$2, path=$3 where hash=$4;
-- name: AddHashToSong :exec
UPDATE song SET hash=$1 where path=$2;
-- name: FindSongsFromGame :many
SELECT *
FROM song
WHERE game_id = $1;
-- name: AddSongPlayed :exec
UPDATE song SET times_played = times_played + 1
WHERE game_id = $1 AND song_name = $2;
-- name: FetchAllSongs :many
SELECT * FROM song;
-- name: RemoveBrokenSong :exec
DELETE FROM song WHERE path = $1;
-- name: RemoveBrokenSongs :exec
DELETE FROM song where path = any (sqlc.slice('paths'));

9
db/queries/song_list.sql Normal file
View File

@@ -0,0 +1,9 @@
-- name: InsertSongInList :exec
INSERT INTO song_list (match_date, match_id, song_no, game_name, song_name)
VALUES ($1, $2, $3, $4, $5);
-- name: GetSongList :many
SELECT *
FROM song_list
WHERE match_date = $1
ORDER BY song_no DESC;

0
db/queries/vgmq.sql Normal file
View File

32
db/repository/db.go Normal file
View File

@@ -0,0 +1,32 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
package repository
import (
"context"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgconn"
)
type DBTX interface {
Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
Query(context.Context, string, ...interface{}) (pgx.Rows, error)
QueryRow(context.Context, string, ...interface{}) pgx.Row
}
func New(db DBTX) *Queries {
return &Queries{db: db}
}
type Queries struct {
db DBTX
}
func (q *Queries) WithTx(tx pgx.Tx) *Queries {
return &Queries{
db: tx,
}
}

246
db/repository/game.sql.go Normal file
View File

@@ -0,0 +1,246 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
// source: game.sql
package repository
import (
"context"
)
const addGamePlayed = `-- name: AddGamePlayed :exec
UPDATE game SET times_played = times_played + 1, last_played = now() WHERE id = $1
`
func (q *Queries) AddGamePlayed(ctx context.Context, id int32) error {
_, err := q.db.Exec(ctx, addGamePlayed, id)
return err
}
const clearGames = `-- name: ClearGames :exec
DELETE FROM game
`
func (q *Queries) ClearGames(ctx context.Context) error {
_, err := q.db.Exec(ctx, clearGames)
return err
}
const findAllGames = `-- name: FindAllGames :many
SELECT id, game_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs, hash
FROM game
WHERE deleted IS NULL
ORDER BY game_name
`
func (q *Queries) FindAllGames(ctx context.Context) ([]Game, error) {
rows, err := q.db.Query(ctx, findAllGames)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Game
for rows.Next() {
var i Game
if err := rows.Scan(
&i.ID,
&i.GameName,
&i.Added,
&i.Deleted,
&i.LastChanged,
&i.Path,
&i.TimesPlayed,
&i.LastPlayed,
&i.NumberOfSongs,
&i.Hash,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getAllGamesIncludingDeleted = `-- name: GetAllGamesIncludingDeleted :many
SELECT id, game_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs, hash
FROM game
ORDER BY game_name
`
func (q *Queries) GetAllGamesIncludingDeleted(ctx context.Context) ([]Game, error) {
rows, err := q.db.Query(ctx, getAllGamesIncludingDeleted)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Game
for rows.Next() {
var i Game
if err := rows.Scan(
&i.ID,
&i.GameName,
&i.Added,
&i.Deleted,
&i.LastChanged,
&i.Path,
&i.TimesPlayed,
&i.LastPlayed,
&i.NumberOfSongs,
&i.Hash,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getGameById = `-- name: GetGameById :one
SELECT id, game_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs, hash
FROM game
WHERE id = $1
AND deleted IS NULL
`
func (q *Queries) GetGameById(ctx context.Context, id int32) (Game, error) {
row := q.db.QueryRow(ctx, getGameById, id)
var i Game
err := row.Scan(
&i.ID,
&i.GameName,
&i.Added,
&i.Deleted,
&i.LastChanged,
&i.Path,
&i.TimesPlayed,
&i.LastPlayed,
&i.NumberOfSongs,
&i.Hash,
)
return i, err
}
const getGameNameById = `-- name: GetGameNameById :one
SELECT game_name FROM game WHERE id = $1
`
func (q *Queries) GetGameNameById(ctx context.Context, id int32) (string, error) {
row := q.db.QueryRow(ctx, getGameNameById, id)
var game_name string
err := row.Scan(&game_name)
return game_name, err
}
const getIdByGameName = `-- name: GetIdByGameName :one
SELECT id FROM game WHERE game_name = $1
`
func (q *Queries) GetIdByGameName(ctx context.Context, gameName string) (int32, error) {
row := q.db.QueryRow(ctx, getIdByGameName, gameName)
var id int32
err := row.Scan(&id)
return id, err
}
const insertGame = `-- name: InsertGame :one
INSERT INTO game (game_name, path, hash, added) VALUES ($1, $2, $3, now()) returning id
`
type InsertGameParams struct {
GameName string `json:"game_name"`
Path string `json:"path"`
Hash string `json:"hash"`
}
func (q *Queries) InsertGame(ctx context.Context, arg InsertGameParams) (int32, error) {
row := q.db.QueryRow(ctx, insertGame, arg.GameName, arg.Path, arg.Hash)
var id int32
err := row.Scan(&id)
return id, err
}
const insertGameWithExistingId = `-- name: InsertGameWithExistingId :exec
INSERT INTO game (id, game_name, path, hash, added) VALUES ($1, $2, $3, $4, now())
`
type InsertGameWithExistingIdParams struct {
ID int32 `json:"id"`
GameName string `json:"game_name"`
Path string `json:"path"`
Hash string `json:"hash"`
}
func (q *Queries) InsertGameWithExistingId(ctx context.Context, arg InsertGameWithExistingIdParams) error {
_, err := q.db.Exec(ctx, insertGameWithExistingId,
arg.ID,
arg.GameName,
arg.Path,
arg.Hash,
)
return err
}
const removeDeletionDate = `-- name: RemoveDeletionDate :exec
UPDATE game SET deleted=NULL WHERE id=$1
`
func (q *Queries) RemoveDeletionDate(ctx context.Context, id int32) error {
_, err := q.db.Exec(ctx, removeDeletionDate, id)
return err
}
const resetGameIdSeq = `-- name: ResetGameIdSeq :one
SELECT setval('game_id_seq', (SELECT MAX(id) FROM game)+1)
`
func (q *Queries) ResetGameIdSeq(ctx context.Context) (int64, error) {
row := q.db.QueryRow(ctx, resetGameIdSeq)
var setval int64
err := row.Scan(&setval)
return setval, err
}
const setGameDeletionDate = `-- name: SetGameDeletionDate :exec
UPDATE game SET deleted=now() WHERE deleted IS NULL
`
func (q *Queries) SetGameDeletionDate(ctx context.Context) error {
_, err := q.db.Exec(ctx, setGameDeletionDate)
return err
}
const updateGameHash = `-- name: UpdateGameHash :exec
UPDATE game SET hash=$1, last_changed=now() WHERE id=$2
`
type UpdateGameHashParams struct {
Hash string `json:"hash"`
ID int32 `json:"id"`
}
func (q *Queries) UpdateGameHash(ctx context.Context, arg UpdateGameHashParams) error {
_, err := q.db.Exec(ctx, updateGameHash, arg.Hash, arg.ID)
return err
}
const updateGameName = `-- name: UpdateGameName :exec
UPDATE game SET game_name=$1, path=$2, last_changed=now() WHERE id=$3
`
type UpdateGameNameParams struct {
Name string `json:"name"`
Path string `json:"path"`
ID int32 `json:"id"`
}
func (q *Queries) UpdateGameName(ctx context.Context, arg UpdateGameNameParams) error {
_, err := q.db.Exec(ctx, updateGameName, arg.Name, arg.Path, arg.ID)
return err
}

47
db/repository/models.go Normal file
View File

@@ -0,0 +1,47 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
package repository
import (
"time"
)
type Game struct {
ID int32 `json:"id"`
GameName string `json:"game_name"`
Added time.Time `json:"added"`
Deleted *time.Time `json:"deleted"`
LastChanged *time.Time `json:"last_changed"`
Path string `json:"path"`
TimesPlayed *int32 `json:"times_played"`
LastPlayed *time.Time `json:"last_played"`
NumberOfSongs int32 `json:"number_of_songs"`
Hash string `json:"hash"`
}
type Song struct {
GameID int32 `json:"game_id"`
SongName string `json:"song_name"`
Path string `json:"path"`
TimesPlayed *int32 `json:"times_played"`
Hash string `json:"hash"`
FileName *string `json:"file_name"`
}
type SongList struct {
MatchDate time.Time `json:"match_date"`
MatchID int32 `json:"match_id"`
SongNo int32 `json:"song_no"`
GameName *string `json:"game_name"`
SongName *string `json:"song_name"`
}
type Vgmq struct {
SongNo int32 `json:"song_no"`
Path *string `json:"path"`
Clue *string `json:"clue"`
Answered bool `json:"answered"`
Answer *string `json:"answer"`
}

223
db/repository/song.sql.go Normal file
View File

@@ -0,0 +1,223 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
// source: song.sql
package repository
import (
"context"
)
const addHashToSong = `-- name: AddHashToSong :exec
UPDATE song SET hash=$1 where path=$2
`
type AddHashToSongParams struct {
Hash string `json:"hash"`
Path string `json:"path"`
}
func (q *Queries) AddHashToSong(ctx context.Context, arg AddHashToSongParams) error {
_, err := q.db.Exec(ctx, addHashToSong, arg.Hash, arg.Path)
return err
}
const addSong = `-- name: AddSong :exec
INSERT INTO song(game_id, song_name, path, file_name, hash) VALUES ($1, $2, $3, $4, $5)
`
type AddSongParams struct {
GameID int32 `json:"game_id"`
SongName string `json:"song_name"`
Path string `json:"path"`
FileName *string `json:"file_name"`
Hash string `json:"hash"`
}
func (q *Queries) AddSong(ctx context.Context, arg AddSongParams) error {
_, err := q.db.Exec(ctx, addSong,
arg.GameID,
arg.SongName,
arg.Path,
arg.FileName,
arg.Hash,
)
return err
}
const addSongPlayed = `-- name: AddSongPlayed :exec
UPDATE song SET times_played = times_played + 1
WHERE game_id = $1 AND song_name = $2
`
type AddSongPlayedParams struct {
GameID int32 `json:"game_id"`
SongName string `json:"song_name"`
}
func (q *Queries) AddSongPlayed(ctx context.Context, arg AddSongPlayedParams) error {
_, err := q.db.Exec(ctx, addSongPlayed, arg.GameID, arg.SongName)
return err
}
const checkSong = `-- name: CheckSong :one
SELECT COUNT(*) FROM song WHERE path = $1
`
func (q *Queries) CheckSong(ctx context.Context, path string) (int64, error) {
row := q.db.QueryRow(ctx, checkSong, path)
var count int64
err := row.Scan(&count)
return count, err
}
const checkSongWithHash = `-- name: CheckSongWithHash :one
SELECT COUNT(*) FROM song WHERE hash = $1
`
func (q *Queries) CheckSongWithHash(ctx context.Context, hash string) (int64, error) {
row := q.db.QueryRow(ctx, checkSongWithHash, hash)
var count int64
err := row.Scan(&count)
return count, err
}
const clearSongs = `-- name: ClearSongs :exec
DELETE FROM song
`
func (q *Queries) ClearSongs(ctx context.Context) error {
_, err := q.db.Exec(ctx, clearSongs)
return err
}
const clearSongsByGameId = `-- name: ClearSongsByGameId :exec
DELETE FROM song WHERE game_id = $1
`
func (q *Queries) ClearSongsByGameId(ctx context.Context, gameID int32) error {
_, err := q.db.Exec(ctx, clearSongsByGameId, gameID)
return err
}
const fetchAllSongs = `-- name: FetchAllSongs :many
SELECT game_id, song_name, path, times_played, hash, file_name FROM song
`
func (q *Queries) FetchAllSongs(ctx context.Context) ([]Song, error) {
rows, err := q.db.Query(ctx, fetchAllSongs)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Song
for rows.Next() {
var i Song
if err := rows.Scan(
&i.GameID,
&i.SongName,
&i.Path,
&i.TimesPlayed,
&i.Hash,
&i.FileName,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const findSongsFromGame = `-- name: FindSongsFromGame :many
SELECT game_id, song_name, path, times_played, hash, file_name
FROM song
WHERE game_id = $1
`
func (q *Queries) FindSongsFromGame(ctx context.Context, gameID int32) ([]Song, error) {
rows, err := q.db.Query(ctx, findSongsFromGame, gameID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Song
for rows.Next() {
var i Song
if err := rows.Scan(
&i.GameID,
&i.SongName,
&i.Path,
&i.TimesPlayed,
&i.Hash,
&i.FileName,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const getSongWithHash = `-- name: GetSongWithHash :one
SELECT game_id, song_name, path, times_played, hash, file_name FROM song WHERE hash = $1
`
func (q *Queries) GetSongWithHash(ctx context.Context, hash string) (Song, error) {
row := q.db.QueryRow(ctx, getSongWithHash, hash)
var i Song
err := row.Scan(
&i.GameID,
&i.SongName,
&i.Path,
&i.TimesPlayed,
&i.Hash,
&i.FileName,
)
return i, err
}
const removeBrokenSong = `-- name: RemoveBrokenSong :exec
DELETE FROM song WHERE path = $1
`
func (q *Queries) RemoveBrokenSong(ctx context.Context, path string) error {
_, err := q.db.Exec(ctx, removeBrokenSong, path)
return err
}
const removeBrokenSongs = `-- name: RemoveBrokenSongs :exec
DELETE FROM song where path = any ($1)
`
func (q *Queries) RemoveBrokenSongs(ctx context.Context, paths []string) error {
_, err := q.db.Exec(ctx, removeBrokenSongs, paths)
return err
}
const updateSong = `-- name: UpdateSong :exec
UPDATE song SET song_name=$1, file_name=$2, path=$3 where hash=$4
`
type UpdateSongParams struct {
SongName string `json:"song_name"`
FileName *string `json:"file_name"`
Path string `json:"path"`
Hash string `json:"hash"`
}
func (q *Queries) UpdateSong(ctx context.Context, arg UpdateSongParams) error {
_, err := q.db.Exec(ctx, updateSong,
arg.SongName,
arg.FileName,
arg.Path,
arg.Hash,
)
return err
}

View File

@@ -0,0 +1,68 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.27.0
// source: song_list.sql
package repository
import (
"context"
"time"
)
const getSongList = `-- name: GetSongList :many
SELECT match_date, match_id, song_no, game_name, song_name
FROM song_list
WHERE match_date = $1
ORDER BY song_no DESC
`
func (q *Queries) GetSongList(ctx context.Context, matchDate time.Time) ([]SongList, error) {
rows, err := q.db.Query(ctx, getSongList, matchDate)
if err != nil {
return nil, err
}
defer rows.Close()
var items []SongList
for rows.Next() {
var i SongList
if err := rows.Scan(
&i.MatchDate,
&i.MatchID,
&i.SongNo,
&i.GameName,
&i.SongName,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const insertSongInList = `-- name: InsertSongInList :exec
INSERT INTO song_list (match_date, match_id, song_no, game_name, song_name)
VALUES ($1, $2, $3, $4, $5)
`
type InsertSongInListParams struct {
MatchDate time.Time `json:"match_date"`
MatchID int32 `json:"match_id"`
SongNo int32 `json:"song_no"`
GameName *string `json:"game_name"`
SongName *string `json:"song_name"`
}
func (q *Queries) InsertSongInList(ctx context.Context, arg InsertSongInListParams) error {
_, err := q.db.Exec(ctx, insertSongInList,
arg.MatchDate,
arg.MatchID,
arg.SongNo,
arg.GameName,
arg.SongName,
)
return err
}