package main import ( "context" "fmt" "github.com/jackc/pgtype" "github.com/jackc/pgx/v4/pgxpool" "os" "time" ) var dbPool *pgxpool.Pool func initDB(host string, port int, user string, password string, dbname string) { psqlInfo := fmt.Sprintf("host=%s port=%d user=%s "+ "password=%s dbname=%s sslmode=disable", host, port, user, password, dbname) fmt.Println(psqlInfo) var err error dbPool, err = pgxpool.Connect(context.Background(), psqlInfo) if err != nil { _, _ = fmt.Fprintf(os.Stderr, "Unable to connect to database: %v\n", err) os.Exit(1) } var success string err = dbPool.QueryRow(context.Background(), "select 'Successfully connected!'").Scan(&success) if err != nil { _, _ = fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", err) os.Exit(1) } fmt.Println(success) } func closeDb() { dbPool.Close() } func getGameName(gameId int) string { var gameName = "" err := dbPool.QueryRow(context.Background(), "SELECT game_name FROM game WHERE id = $1", gameId).Scan(&gameName) if err != nil { _, _ = fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", err) return "" } return gameName } func setGameDeletionDate() { _, err := dbPool.Exec(context.Background(), "UPDATE game SET deleted=$1", time.Now()) if err != nil { _, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err) } } func clearSongs(gameId int) { if gameId == -1 { _, err := dbPool.Exec(context.Background(), "DELETE FROM song") if err != nil { _, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err) } } else { _, err := dbPool.Exec(context.Background(), "DELETE FROM song where game_id=$1", gameId) if err != nil { _, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err) } } } func clearGames() { _, err := dbPool.Exec(context.Background(), "DELETE FROM game") if err != nil { _, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err) } } func updateGameName(id int, name string, path string) { _, err := dbPool.Exec(context.Background(), "UPDATE game SET game_name=$1, path=$2, last_changed=$3 WHERE id=$4", name, path, time.Now(), id) if err != nil { _, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err) } } func removeDeletionDate(id int) { _, err := dbPool.Exec(context.Background(), "UPDATE game SET deleted=null WHERE id=$1", id) if err != nil { _, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err) } } func addSong(song SongData) { _, err := dbPool.Exec(context.Background(), "INSERT INTO song(game_id, song_name, path) VALUES ($1, $2, $3)", song.gameId, song.songName, song.path) if err != nil { _, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err) } } func findSongsFromGame(id int) []SongData { rows, err := dbPool.Query(context.Background(), "SELECT song_name, path, times_played FROM song WHERE game_id = $1", id) if err != nil { _, _ = fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", err) return nil } var songDataList []SongData for rows.Next() { var songName string var path string var timesPlayed int err := rows.Scan(&songName, &path, ×Played) if err != nil { _, _ = fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", err) } songDataList = append(songDataList, SongData{ gameId: id, songName: songName, path: path, timesPlayed: timesPlayed, }) } return songDataList } func getIdByGameName(name string) int { var gameId = -1 err := dbPool.QueryRow(context.Background(), "SELECT id FROM game WHERE game_name = $1", name).Scan(&gameId) if err != nil { _, _ = fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", err) return -1 } return gameId } func insertGame(name string, path string) int { gameId := -1 err := dbPool.QueryRow(context.Background(), "INSERT INTO game(game_name, path, added) VALUES ($1, $2, $3) RETURNING id", name, path, time.Now()).Scan(&gameId) if err != nil { _, _ = fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", err) resetGameIdSeq() err2 := dbPool.QueryRow(context.Background(), "INSERT INTO game(game_name, path, added) VALUES ($1, $2, $3) RETURNING id", name, path, time.Now()).Scan(&gameId) if err2 != nil { _, _ = fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", err) return -1 } } return gameId } func insertGameWithExistingId(id int, name string, path string) { _, err := dbPool.Exec(context.Background(), "INSERT INTO game(id, game_name, path, added) VALUES ($1, $2, $3, $4)", id, name, path, time.Now()) if err != nil { _, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err) } } func resetGameIdSeq() { _, err := dbPool.Query(context.Background(), "SELECT setval('game_id_seq', (SELECT MAX(id) FROM game)+1);") if err != nil { _, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err) } } func findAllGames() []GameData { rows, err := dbPool.Query(context.Background(), "SELECT id, game_name, added, deleted, last_changed, path, times_played, last_played, number_of_songs "+ "FROM game "+ "ORDER BY game_name") if err != nil { _, _ = fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", err) } var gameList []GameData for rows.Next() { var id, timesPlayed int var numberOfSongs pgtype.Int4 var gameName, path string var added, deleted, lastChanged, lastPlayed pgtype.Timestamp err := rows.Scan(&id, &gameName, &added, &deleted, &lastChanged, &path, ×Played, &lastPlayed, &numberOfSongs) if err != nil { _, _ = fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", err) } gameList = append(gameList, GameData{ id: id, gameName: gameName, added: added.Time, deleted: deleted.Time, lastChanged: lastChanged.Time, path: path, timesPlayed: timesPlayed, lastPlayed: lastPlayed.Time, numberOfSongs: numberOfSongs.Int, }) } return gameList } func addGamePlayed(id int) { _, err := dbPool.Exec(context.Background(), "UPDATE game SET times_played=times_played+1, last_played=now() WHERE id=$1", id) if err != nil { _, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err) } } func addSongPlayed(id int, name string) { _, err := dbPool.Exec(context.Background(), "UPDATE song SET times_played=times_played+1 WHERE game_id=$1 AND song_name=$2", id, name) if err != nil { _, _ = fmt.Fprintf(os.Stderr, "Exec failed: %v\n", err) } } func testf() { rows, dbErr := dbPool.Query(context.Background(), "select game_name from game") if dbErr != nil { _, _ = fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", dbErr) os.Exit(1) } for rows.Next() { var gameName string dbErr = rows.Scan(&gameName) if dbErr != nil { _, _ = fmt.Fprintf(os.Stderr, "QueryRow failed: %v\n", dbErr) } _, _ = fmt.Fprintf(os.Stderr, "%v\n", gameName) } }