package guest import ( "context" "errors" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" ) type Store struct { database *pgxpool.Pool } func NewStore(database *pgxpool.Pool) *Store { return &Store{ database, } } func (store Store) Find(credentials Credentials) (Guest, error) { guestRows, err := store.database.Query(context.Background(), "select * from guest") if err != nil { return Guest{}, err } defer guestRows.Close() guest, found := createGuest(credentials, guestRows) partyRows, err := store.database.Query(context.Background(), "select * from party") if err != nil { return Guest{}, err } defer partyRows.Close() guest, err = addParty(guest, partyRows) if err != nil { return Guest{}, err } if found { return guest, nil } return Guest{}, errors.New("guest not found") } func createGuest(credentials Credentials, guestRows pgx.Rows) (Guest, bool) { var guest Guest for guestRows.Next() { err := guestRows.Scan(&guest.ID, &guest.FirstName, &guest.LastName, &guest.Attendance, &guest.Email, &guest.Message, &guest.PartySize) if err != nil { return Guest{}, false } if guest.FirstName == credentials.FirstName && guest.LastName == credentials.LastName { return guest, true } } return Guest{}, false } func addParty(guestWithoutParty Guest, partyRows pgx.Rows) (Guest, error) { guestWithParty := guestWithoutParty for partyRows.Next() { var guestID int var partyGuest PartyGuest err := partyRows.Scan(&guestID, &partyGuest.FirstName, &partyGuest.LastName) if err != nil { return Guest{}, err } if guestID == guestWithParty.ID { guestWithParty.PartyList = append(guestWithParty.PartyList, partyGuest) } } return guestWithParty, nil } func (store Store) Get() ([]Guest, error) { guestRows, err := store.database.Query(context.Background(), "select * from guest") if err != nil { return nil, err } defer guestRows.Close() guestsWithoutParty, err := store.createGuestSlice(guestRows) if err != nil { return []Guest{}, err } partyRows, err := store.database.Query(context.Background(), "select * from party") if err != nil { return []Guest{}, err } defer partyRows.Close() guestsWithParty, err := addPartySlice(guestsWithoutParty, partyRows) if err != nil { return []Guest{}, err } return guestsWithParty, nil } func (store Store) createGuestSlice(guestRows pgx.Rows) ([]Guest, error) { guests := []Guest{} for guestRows.Next() { var guest Guest err := guestRows.Scan(&guest.ID, &guest.FirstName, &guest.LastName, &guest.Attendance, &guest.Email, &guest.Message, &guest.PartySize) if err != nil { return []Guest{}, err } guests = append(guests, guest) } return guests, nil } func addPartySlice(guestsWithoutParty []Guest, partyRows pgx.Rows) ([]Guest, error) { guestsWithParty := guestsWithoutParty for partyRows.Next() { var guestID int var partyGuest PartyGuest err := partyRows.Scan(&guestID, &partyGuest.FirstName, &partyGuest.LastName) if err != nil { return []Guest{}, err } for i, guest := range guestsWithParty { if guestID == guest.ID { guestsWithParty[i].PartyList = append(guest.PartyList, partyGuest) } } } return guestsWithParty, nil } func (store Store) Add(guest Guest) error { if err := store.insertGuest(guest); err != nil { return err } return store.insertParty(guest) } func (store Store) insertGuest(guest Guest) error { statement := `insert into guest (id, first_name, last_name, attendance, email, message, party_size) values ($1, $2, $3, $4, $5, $6, $7)` _, err := store.database.Exec(context.Background(), statement, guest.ID, guest.FirstName, guest.LastName, guest.Attendance, guest.Email, guest.Message, guest.PartySize) return err } func (store Store) Update(guest Guest) error { if err := store.updateGuest(guest); err != nil { return err } if err := store.deleteOldParty(guest.ID); err != nil { return err } return store.insertParty(guest) } func (store Store) updateGuest(guest Guest) error { statement := `update guest set attendance = $1, email = $2, message = $3, party_size = $4 where id = $5` _, err := store.database.Exec(context.Background(), statement, guest.Attendance, guest.Email, guest.Message, guest.PartySize, guest.ID) return err } func (store Store) deleteOldParty(guestID int) error { statement := "delete from party where guest_id = $1" _, err := store.database.Exec(context.Background(), statement, guestID) return err } func (store Store) insertParty(guest Guest) error { statement := `insert into party (guest_id, first_name, last_name) values ($1, $2, $3)` for _, pg := range guest.PartyList { _, err := store.database.Exec(context.Background(), statement, guest.ID, pg.FirstName, pg.LastName) if err != nil { return err } } return nil }