package mysql import ( "context" "database/sql" "encoding/json" "git.aiterp.net/lucifer/new-server/models" "github.com/jmoiron/sqlx" ) type sceneRecord struct { ID int `db:"id"` Name string `db:"name"` IntervalMS int64 `db:"interval_ms"` RoleJSON json.RawMessage `db:"roles"` } type SceneRepo struct { DBX *sqlx.DB } func (r *SceneRepo) Find(ctx context.Context, id int) (*models.Scene, error) { var scene sceneRecord err := r.DBX.GetContext(ctx, &scene, "SELECT * FROM scene WHERE id = ?", id) if err != nil { return nil, dbErr(err) } return r.populateOne(&scene) } func (r *SceneRepo) FetchAll(ctx context.Context) ([]models.Scene, error) { scenes := make([]sceneRecord, 0, 8) err := r.DBX.SelectContext(ctx, &scenes, "SELECT * FROM scene") if err != nil { if err == sql.ErrNoRows { return []models.Scene{}, nil } return nil, dbErr(err) } return r.populate(scenes) } func (r *SceneRepo) Save(ctx context.Context, scene *models.Scene) error { j, err := json.Marshal(scene.Roles) if err != nil { return err } if scene.ID > 0 { _, err := r.DBX.ExecContext( ctx, "UPDATE scene SET name = ?, interval_ms = ?, roles = ? WHERE id = ?", scene.Name, scene.IntervalMS, j, scene.ID, ) if err != nil { return dbErr(err) } } else { rs, err := r.DBX.ExecContext( ctx, "INSERT INTO scene (name, interval_ms, roles) VALUES (?, ?, ?)", scene.Name, scene.IntervalMS, j, ) if err != nil { return dbErr(err) } id, err := rs.LastInsertId() if err != nil { return dbErr(err) } scene.ID = int(id) } return nil } func (r *SceneRepo) Delete(ctx context.Context, scene *models.Scene) error { _, err := r.DBX.ExecContext(ctx, "DELETE FROM scene WHERE id = ?", scene.ID) if err != nil { return dbErr(err) } scene.ID = 0 return nil } func (r *SceneRepo) populateOne(record *sceneRecord) (*models.Scene, error) { records, err := r.populate([]sceneRecord{*record}) if err != nil { return nil, err } return &records[0], nil } func (r *SceneRepo) populate(records []sceneRecord) ([]models.Scene, error) { res := make([]models.Scene, 0, len(records)) for _, record := range records { scene := models.Scene{ ID: record.ID, Name: record.Name, IntervalMS: record.IntervalMS, Roles: make([]models.SceneRole, 0, 8), } err := json.Unmarshal(record.RoleJSON, &scene.Roles) if err != nil { return nil, dbErr(err) } res = append(res, scene) } return res, nil }