Rework query to return lists

This commit is contained in:
2024-10-27 19:07:47 +01:00
parent 91a3a0f4f7
commit b86d586c42
4 changed files with 222 additions and 148 deletions

View File

@@ -12,20 +12,30 @@ type GuildServiceQuery struct {
ID *int64 `db:"id"` ID *int64 `db:"id"`
} }
func (gs *GuildService) Query(query GuildServiceQuery) (Guild, error) { func (gs *GuildService) Query(query GuildServiceQuery) ([]Guild, error) {
guild := Guild{} res := []Guild{}
sqlQuery := "SELECT id, name FROM guild" sqlQuery := "SELECT id, name FROM guild"
whereQuery := BuildWhereQuery(query) whereQuery := BuildWhereQuery(query)
if whereQuery != "" { if whereQuery != "" {
sqlQuery += " " + whereQuery sqlQuery += " " + whereQuery
} }
err := gs.db.readConn.QueryRow(sqlQuery).Scan(&guild.ID, &guild.Name) rows, err := gs.db.readConn.Query(sqlQuery)
if err != nil { if err != nil {
return guild, fmt.Errorf("failed getting guild for query %q: %v", sqlQuery, err) return res, fmt.Errorf("failed getting guilds for query %q: %v", sqlQuery, err)
}
defer rows.Close()
for rows.Next() {
guild := Guild{}
err := rows.Scan(&guild.ID, &guild.Name)
if err != nil {
return res, fmt.Errorf("failed scanning guild: %v", err)
}
res = append(res, guild)
} }
return guild, nil return res, nil
} }
func (gs *GuildService) Create(name string) (Guild, error) { func (gs *GuildService) Create(name string) (Guild, error) {
@@ -40,13 +50,24 @@ func (gs *GuildService) Create(name string) (Guild, error) {
return guild, fmt.Errorf("failed to get last insert id: %v", err) return guild, fmt.Errorf("failed to get last insert id: %v", err)
} }
return gs.Query(GuildServiceQuery{ID: &id}) qres, err := gs.Query(GuildServiceQuery{ID: &id})
if err != nil {
return guild, fmt.Errorf("failed getting guild for id %d: %v", id, err)
}
if len(qres) > 1 {
return guild, fmt.Errorf("more than one guild found for id %d", id)
}
return qres[0], nil
} }
func (gs *GuildService) GetOrCreate(name string) (Guild, error) { func (gs *GuildService) GetOrCreate(name string) (Guild, error) {
guild := Guild{} guild := Guild{}
guild, err := gs.Query(GuildServiceQuery{Name: &name}) guilds, err := gs.Query(GuildServiceQuery{Name: &name})
if err != nil { if err != nil {
if len(guilds) > 1 {
return guild, fmt.Errorf("more than one guild found for name %s", name)
}
guild, err = gs.Create(name) guild, err = gs.Create(name)
if err != nil { if err != nil {
return guild, fmt.Errorf("failed creating guild: %v", err) return guild, fmt.Errorf("failed creating guild: %v", err)

270
main.go
View File

@@ -6,8 +6,6 @@ import (
"io" "io"
"log" "log"
"os" "os"
"strings"
"time"
) )
var Error *log.Logger var Error *log.Logger
@@ -32,6 +30,9 @@ func init() {
} }
var db DB var db DB
var gs GuildService
var ps PlayerService
var ns NoteService
func main() { func main() {
inputFile := flag.String("if", "input", "Input file") inputFile := flag.String("if", "input", "Input file")
@@ -48,155 +49,168 @@ func main() {
} }
defer db.Close() defer db.Close()
gs = GuildService{db: &db}
ps = PlayerService{db: &db}
ns = NoteService{db: &db}
inputData, err := os.ReadFile(*inputFile) inputData, err := os.ReadFile(*inputFile)
if err != nil { if err != nil {
Error.Printf("Failed reading input file: %v", err) Error.Printf("Failed reading input file: %v", err)
return return
} }
note, err := ParseNote(string(inputData)) log.Printf("%#v", string(inputData))
res, err := gs.Query(GuildServiceQuery{})
if err != nil { if err != nil {
Error.Printf("Failed parsing note: %v", err) Error.Printf("Failed getting guilds: %v", err)
return return
} }
log.Printf("%#v", res)
// note, err := ParseNote(string(inputData))
// if err != nil {
// Error.Printf("Failed parsing note: %v", err)
// return
// }
err = SaveNote(note) // err = SaveNote(note)
if err != nil { // if err != nil {
Error.Printf("Failed saving note: %v", err) // Error.Printf("Failed saving note: %v", err)
return // return
} // }
} }
func ParseNote(data string) (NoteData, error) { // func ParseNote(data string) (NoteData, error) {
res := NoteData{} // res := NoteData{}
lines := strings.Split(data, "\n") // lines := strings.Split(data, "\n")
note := []string{} // note := []string{}
for _, line := range lines { // for _, line := range lines {
line = strings.TrimSpace(line) // line = strings.TrimSpace(line)
if line == "" { // if line == "" {
continue // continue
} // }
parts := strings.Split(line, ":") // parts := strings.Split(line, ":")
switch parts[0] { // switch parts[0] {
case "p": // case "p":
res.Player = parts[1] // res.Player = parts[1]
case "d": // case "d":
var err error // var err error
res.Date, err = time.Parse(time.DateOnly, parts[1]) // res.Date, err = time.Parse(time.DateOnly, parts[1])
if err != nil { // if err != nil {
return res, fmt.Errorf("failed to parse date: %v", err) // return res, fmt.Errorf("failed to parse date: %v", err)
} // }
case "g": // case "g":
res.Guild = parts[1] // res.Guild = parts[1]
default: // default:
note = append(note, line) // note = append(note, line)
} // }
} // }
res.Note = strings.Join(note, "\n") // res.Note = strings.Join(note, "\n")
return res, nil // return res, nil
} // }
func SaveNote(data NoteData) error { // func SaveNote(data NoteData) error {
guild, err := GetOrCreateGuildByName(data.Guild) // guild, err := GetOrCreateGuildByName(data.Guild)
if err != nil { // if err != nil {
return fmt.Errorf("failed getting guild for %s: %v", data.Guild, err) // return fmt.Errorf("failed getting guild for %s: %v", data.Guild, err)
} // }
stinky, err := GetOrCreateStinkyByName(data.Player, guild) // stinky, err := GetOrCreateStinkyByName(data.Player, guild)
if err != nil { // if err != nil {
return fmt.Errorf("failed getting stinky for %s: %v", data.Player, err) // return fmt.Errorf("failed getting stinky for %s: %v", data.Player, err)
} // }
stinky.Guild = guild // stinky.Guild = guild
note := Note{ // note := Note{
Content: data.Note, // Content: data.Note,
Timestamp: data.Date, // Timestamp: data.Date,
Stinky: stinky, // Stinky: stinky,
} // }
err = InsertNote(note) // err = InsertNote(note)
if err != nil { // if err != nil {
return fmt.Errorf("failed inserting note: %v", err) // return fmt.Errorf("failed inserting note: %v", err)
} // }
return nil // return nil
} // }
func GetOrCreateGuildByName(name string) (Guild, error) { // func GetOrCreateGuildByName(name string) (Guild, error) {
var guild Guild // var guild Guild
err := db.readConn.QueryRow("select id, name from guild where name = ?", name).Scan(&guild.ID, &guild.Name) // err := db.readConn.QueryRow("select id, name from guild where name = ?", name).Scan(&guild.ID, &guild.Name)
if err != nil { // if err != nil {
guild, err = CreateGuild(name) // guild, err = CreateGuild(name)
if err != nil { // if err != nil {
return guild, fmt.Errorf("failed creating guild: %v", err) // return guild, fmt.Errorf("failed creating guild: %v", err)
} // }
} // }
return guild, nil // return guild, nil
} // }
func CreateGuild(name string) (Guild, error) { // func CreateGuild(name string) (Guild, error) {
guild := Guild{} // guild := Guild{}
res, err := db.writeConn.Exec("insert into guild (name) values (?)", name) // res, err := db.writeConn.Exec("insert into guild (name) values (?)", name)
if err != nil { // if err != nil {
return guild, fmt.Errorf("failed to insert guild: %v", err) // return guild, fmt.Errorf("failed to insert guild: %v", err)
} // }
id, err := res.LastInsertId() // id, err := res.LastInsertId()
if err != nil { // if err != nil {
return guild, fmt.Errorf("failed to get last insert id: %v", err) // return guild, fmt.Errorf("failed to get last insert id: %v", err)
} // }
return GetGuildById(int(id)) // return GetGuildById(int(id))
} // }
func GetGuildById(id int) (Guild, error) { // func GetGuildById(id int) (Guild, error) {
var guild Guild // var guild Guild
err := db.readConn.QueryRow("select id, name from guild where id = ?", id).Scan(&guild.ID, &guild.Name) // err := db.readConn.QueryRow("select id, name from guild where id = ?", id).Scan(&guild.ID, &guild.Name)
if err != nil { // if err != nil {
log.Printf("Guild not found: %v", err) // log.Printf("Guild not found: %v", err)
} // }
return guild, nil // return guild, nil
} // }
func GetOrCreateStinkyByName(name string, guild Guild) (Stinky, error) { // func GetOrCreateStinkyByName(name string, guild Guild) (Stinky, error) {
var stinky Stinky // var stinky Stinky
err := db.readConn.QueryRow("select id, name, guild from stinky where name = ?", name).Scan(&stinky.ID, &stinky.Name, &stinky.Guild.ID) // err := db.readConn.QueryRow("select id, name, guild from stinky where name = ?", name).Scan(&stinky.ID, &stinky.Name, &stinky.Guild.ID)
if err != nil { // if err != nil {
log.Printf("Stinky not found, creating: %v", err) // log.Printf("Stinky not found, creating: %v", err)
stinky, err = CreateStinky(name, Guild{}) // stinky, err = CreateStinky(name, guild)
if err != nil { // if err != nil {
return stinky, fmt.Errorf("failed creating stinky: %v", err) // return stinky, fmt.Errorf("failed creating stinky: %v", err)
} // }
} // }
return stinky, nil // return stinky, nil
} // }
func CreateStinky(name string, guild Guild) (Stinky, error) { // func CreateStinky(name string, guild Guild) (Stinky, error) {
stinky := Stinky{} // stinky := Stinky{}
res, err := db.writeConn.Exec("insert into stinky (name, guild) values (?, ?)", name, guild.ID) // res, err := db.writeConn.Exec("insert into stinky (name, guild) values (?, ?)", name, guild.ID)
if err != nil { // if err != nil {
return stinky, fmt.Errorf("failed to insert stinky: %v", err) // return stinky, fmt.Errorf("failed to insert stinky: %v", err)
} // }
id, err := res.LastInsertId() // id, err := res.LastInsertId()
if err != nil { // if err != nil {
return stinky, fmt.Errorf("failed getting last insert id for %d: %v", id, err) // return stinky, fmt.Errorf("failed getting last insert id for %d: %v", id, err)
} // }
return GetStinkyById(int(id)) // return GetStinkyById(int(id))
} // }
func GetStinkyById(id int) (Stinky, error) { // func GetStinkyById(id int) (Stinky, error) {
stinky := Stinky{} // stinky := Stinky{}
err := db.readConn.QueryRow("select id, name, guild from stinky where id = ?", id).Scan(&stinky.ID, &stinky.Name, &stinky.Guild.ID) // err := db.readConn.QueryRow("select id, name, guild from stinky where id = ?", id).Scan(&stinky.ID, &stinky.Name, &stinky.Guild.ID)
if err != nil { // if err != nil {
return stinky, fmt.Errorf("failed getting stinky for %d: %v", id, err) // return stinky, fmt.Errorf("failed getting stinky for %d: %v", id, err)
} // }
return stinky, nil // return stinky, nil
} // }
func InsertNote(note Note) error { // func InsertNote(note Note) error {
_, err := db.writeConn.Exec("insert into note (content, timestamp, stinky) values (?, ?, ?)", note.Content, note.Timestamp, note.Stinky.ID) // log.Printf("Inserting note: %#v", note)
if err != nil { // _, err := db.writeConn.Exec("insert into note (content, timestamp, stinky) values (?, ?, ?)", note.Content, note.Timestamp, note.Stinky.ID)
return fmt.Errorf("failed to insert note: %v", err) // if err != nil {
} // return fmt.Errorf("failed to insert note: %v", err)
return nil // }
} // return nil
// }

View File

@@ -14,20 +14,30 @@ type NoteServiceQuery struct {
ID *int64 `db:"id"` ID *int64 `db:"id"`
} }
func (ns *NoteService) Query(query NoteServiceQuery) (Note, error) { func (ns *NoteService) Query(query NoteServiceQuery) ([]Note, error) {
note := Note{} res := []Note{}
sqlQuery := "SELECT id, content, timestamp, player FROM note" sqlQuery := "SELECT id, content, timestamp, player FROM note"
whereQuery := BuildWhereQuery(query) whereQuery := BuildWhereQuery(query)
if whereQuery != "" { if whereQuery != "" {
sqlQuery += " " + whereQuery sqlQuery += " " + whereQuery
} }
err := ns.db.readConn.QueryRow(sqlQuery).Scan(&note.ID, &note.Content, &note.Timestamp, &note.Player.ID) rows, err := ns.db.readConn.Query(sqlQuery)
if err != nil { if err != nil {
return note, fmt.Errorf("failed getting note for query %q: %v", sqlQuery, err) return res, fmt.Errorf("failed getting notes for query %q: %v", sqlQuery, err)
}
defer rows.Close()
for rows.Next() {
note := Note{}
err := rows.Scan(&note.ID, &note.Content, &note.Timestamp, &note.Player.ID)
if err != nil {
return res, fmt.Errorf("failed scanning note: %v", err)
}
res = append(res, note)
} }
return note, nil return res, nil
} }
func (ns *NoteService) Create(content string, timestamp time.Time, player Player) (Note, error) { func (ns *NoteService) Create(content string, timestamp time.Time, player Player) (Note, error) {
@@ -42,5 +52,13 @@ func (ns *NoteService) Create(content string, timestamp time.Time, player Player
return note, fmt.Errorf("failed to get last insert id: %v", err) return note, fmt.Errorf("failed to get last insert id: %v", err)
} }
return ns.Query(NoteServiceQuery{ID: &id}) qres, err := ns.Query(NoteServiceQuery{ID: &id})
if err != nil {
return note, fmt.Errorf("failed getting note for id %d: %v", id, err)
}
if len(qres) > 1 {
return note, fmt.Errorf("more than one note found for id %d", id)
}
return qres[0], nil
} }

View File

@@ -10,20 +10,30 @@ type PlayerServiceQuery struct {
ID *int64 `db:"id"` ID *int64 `db:"id"`
} }
func (ps *PlayerService) Query(query PlayerServiceQuery) (Player, error) { func (ps *PlayerService) Query(query PlayerServiceQuery) ([]Player, error) {
player := Player{} res := []Player{}
sqlQuery := "SELECT id, name, guild FROM player" sqlQuery := "SELECT id, name, guild FROM player"
whereQuery := BuildWhereQuery(query) whereQuery := BuildWhereQuery(query)
if whereQuery != "" { if whereQuery != "" {
sqlQuery += " " + whereQuery sqlQuery += " " + whereQuery
} }
err := ps.db.readConn.QueryRow(sqlQuery).Scan(&player.ID, &player.Name, &player.Guild.ID) rows, err := ps.db.readConn.Query(sqlQuery)
if err != nil { if err != nil {
return player, fmt.Errorf("failed getting player for query %q: %v", sqlQuery, err) return res, fmt.Errorf("failed getting players for query %q: %v", sqlQuery, err)
}
defer rows.Close()
for rows.Next() {
player := Player{}
err := rows.Scan(&player.ID, &player.Name, &player.Guild.ID)
if err != nil {
return res, fmt.Errorf("failed scanning player: %v", err)
}
res = append(res, player)
} }
return player, nil return res, nil
} }
func (ps *PlayerService) Create(name string, guild Guild) (Player, error) { func (ps *PlayerService) Create(name string, guild Guild) (Player, error) {
@@ -38,13 +48,24 @@ func (ps *PlayerService) Create(name string, guild Guild) (Player, error) {
return player, fmt.Errorf("failed to get last insert id: %v", err) return player, fmt.Errorf("failed to get last insert id: %v", err)
} }
return ps.Query(PlayerServiceQuery{ID: &id}) qres, err := ps.Query(PlayerServiceQuery{ID: &id})
if err != nil {
return player, fmt.Errorf("failed getting player for id %d: %v", id, err)
}
if len(qres) > 1 {
return player, fmt.Errorf("more than one player found for id %d", id)
}
return qres[0], nil
} }
func (ps *PlayerService) GetOrCreate(name string, guild Guild) (Player, error) { func (ps *PlayerService) GetOrCreate(name string, guild Guild) (Player, error) {
player := Player{} player := Player{}
player, err := ps.Query(PlayerServiceQuery{Name: &name}) players, err := ps.Query(PlayerServiceQuery{Name: &name})
if err != nil { if err != nil {
if len(players) > 1 {
return player, fmt.Errorf("more than one player found for name %s", name)
}
player, err = ps.Create(name, guild) player, err = ps.Create(name, guild)
if err != nil { if err != nil {
return player, fmt.Errorf("failed creating player: %v", err) return player, fmt.Errorf("failed creating player: %v", err)