package main import ( "database/sql" "fmt" "log" "net/url" "strings" ) type Member struct { name string dietaryPreferences string child bool } func (m *Member) serialize() string { builder := new(strings.Builder) fmt.Fprintf(builder, "%s,%s,%t,", url.QueryEscape(m.name), url.QueryEscape(m.dietaryPreferences), m.child) return builder.String() } func deserializeMembers(serializedData string) ([]Member, error) { members := make([]Member, 0) keyVals := strings.Split(serializedData, ",") for i := 0; i < len(keyVals)-1; i += 3 { name, err := url.QueryUnescape(keyVals[i]) if err != nil { return nil, err } dietaryPreferences, err := url.QueryUnescape(keyVals[i+1]) if err != nil { return nil, err } child := keyVals[i+2] == "true" members = append(members, Member{ name: name, dietaryPreferences: dietaryPreferences, child: child, }) } return members, nil } type Rsvp struct { id int64 attending bool partySize int64 partyMembers []Member } func SetupRsvpsTable(db *sql.DB) { _, err := db.Exec(`CREATE TABLE IF NOT EXISTS rsvps ( id INTEGER PRIMARY KEY AUTOINCREMENT, attending BOOLEAN NOT NULL, partySize INTEGER NOT NULL, partyMembers BLOB NOT NULL );`) if err != nil { log.Fatalf("failed to create rsvp table: %s", err.Error()) } } func GetRsvps(db *sql.DB) ([]Rsvp, error) { rows, err := db.Query("SELECT * FROM rsvps ORDER BY id desc") if err != nil { return nil, err } defer rows.Close() rsvps := make([]Rsvp, 0) for rows.Next() { var id int64 var attending bool var partySize int64 var rawPartyMembers string err = rows.Scan(&id, &attending, &partySize, &rawPartyMembers) if err != nil { return nil, err } members, err := deserializeMembers(rawPartyMembers) if err != nil { return nil, err } rsvps = append(rsvps, Rsvp{ id: id, attending: attending, partySize: partySize, partyMembers: members, }) } return rsvps, nil } func (rsvp *Rsvp) CreateRsvp(db *sql.DB) (int64, error) { partyMembersBuilder := new(strings.Builder) for _, m := range rsvp.partyMembers { partyMembersBuilder.WriteString(m.serialize()) } fmt.Printf("%s\n", partyMembersBuilder.String()) result, err := db.Exec( "INSERT INTO rsvps (attending, partySize, partyMembers) VALUES (?, ?, ?);", rsvp.attending, rsvp.partySize, partyMembersBuilder.String(), ) if err != nil { return -1, err } id, err := result.LastInsertId() if err != nil { return -1, err } return id, nil }