package db import ( "context" "database/sql" "errors" "fmt" "github.com/jmoiron/sqlx" "golang.org/x/sync/errgroup" ) type Table struct { ID string Name string Description string Formula string Img string Folder string Sort int Replacement bool DisplayRoll bool Stats Stats Ownership []OwnershipString Results []*TableResult } func (t *Table) Query(data *InsertId[uint]) { data.query = fmt.Sprintf(` INSERT INTO table_ (%s, id, name, description, formula, img, folder, sort, replacement, display_roll) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`, data.fieldName) } func (t *Table) InsertObjects(tx *sqlx.Tx) error { group, ctx := errgroup.WithContext(context.Background()) relId := InsertId[string]{id: t.ID, fieldName: "table_id"} InsertWithCtxParallel(group, ctx, tx, t.Stats, relId) InsertSliceParallel(group, tx, t.Ownership, relId) InsertSliceParallel(group, tx, t.Results, relId) err := group.Wait() if err != nil && !errors.Is(err, sql.ErrNoRows) { return err } return nil } func (t *Table) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { if data.query == "" { return ErrNoQuery } args := []any{data.id, t.ID, t.Name, t.Description, t.Formula, t.Img, t.Folder, t.Sort, t.Replacement, t.DisplayRoll} _, err := tx.Exec(data.query, args...) if err != nil { return err } return t.InsertObjects(tx) } func (t *Table) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { if data.query == "" { return ErrNoQuery } args := []any{data.id, t.ID, t.Name, t.Description, t.Formula, t.Img, t.Folder, t.Sort, t.Replacement, t.DisplayRoll} _, err := tx.ExecContext(ctx, data.query, args...) if err != nil { return err } return t.InsertObjects(tx) } type TableResult struct { ID string Type string Img string Description string Name string Weight int Drawn bool Stats Stats Range []int } func (t *TableResult) Query(data *InsertId[string]) { data.query = fmt.Sprintf(` INSERT INTO table_result (%s, id, type, img, description, name, weight, drawn) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`, data.fieldName) } func (t *TableResult) InsertObjects(tx *sqlx.Tx) error { group, ctx := errgroup.WithContext(context.Background()) InsertWithCtxParallel(group, ctx, tx, t.Stats, InsertId[string]{id: t.ID, fieldName: "table_result_id"}) InsertSimpleSlice(tx, t.Range, &InsertId[string]{id: t.ID, fieldName: "table_result_id", tableName: "table_result_range"}) err := group.Wait() if err != nil && !errors.Is(err, sql.ErrNoRows) { return err } return nil } func (t *TableResult) Insert(tx *sqlx.Tx, data *InsertId[string]) error { if data.query == "" { return ErrNoQuery } args := []any{data.id, t.ID, t.Type, t.Img, t.Description, t.Name, t.Weight, t.Drawn} _, err := tx.Exec(data.query, args...) if err != nil { return err } return t.InsertObjects(tx) } func (t *TableResult) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { if data.query == "" { return ErrNoQuery } args := []any{data.id, t.ID, t.Type, t.Img, t.Description, t.Name, t.Weight, t.Drawn} _, err := tx.ExecContext(ctx, data.query, args...) if err != nil { return err } return t.InsertObjects(tx) }