package entry import ( "time" "code.chrissexton.org/cws/cabinet/db" "github.com/jmoiron/sqlx" "github.com/rs/zerolog/log" ) type Entry struct { db *db.Database ID int64 Slug string Content string Tags []string Created time.Time Updated time.Time AuthorID int64 `db:"author_id"` } func PrepareTable(tx *sqlx.Tx) error { q := `create table if not exists entries ( id integer primary key, slug text unique, content text, created datetime, updated datetime, author_id integer )` _, err := tx.Exec(q) if err != nil { tx.Rollback() return err } q = `create table if not exists tags ( id integer primary key, name text, entry_id integer, foreign key(entry_id) references entries(id) )` _, err = tx.Exec(q) if err != nil { tx.Rollback() return err } return nil } func New(db *db.Database) Entry { return Entry{ db: db, ID: -1, Created: time.Now(), Updated: time.Now(), } } func GetBySlug(db *db.Database, slug string) (Entry, error) { e := Entry{db: db} q := `select * from entries where slug = ?` if err := db.Get(&e, q, slug); err != nil { return e, err } return e, e.populateTags() } func GetByID(db *db.Database, id int64) (Entry, error) { e := Entry{db: db} q := `select * from entries where id = ?` if err := db.Get(&e, q, id); err != nil { return e, err } return e, e.populateTags() } func GetAll(db *db.Database) ([]*Entry, error) { entries := []*Entry{} q := `select * from entries` err := db.Select(&entries, q) if err != nil { return nil, err } for _, e := range entries { e.db = db e.populateTags() } return entries, nil } func RemoveBySlug(db *db.Database, slug string) error { tx, err := db.Begin() if err != nil { return err } e, err := GetBySlug(db, slug) if err != nil { return err } q := `delete from tags where entry_id = ?` if _, err := tx.Exec(q, e.ID); err != nil { tx.Rollback() return err } q = `delete from entries where entry_id = ?` if _, err := tx.Exec(q, e.ID); err != nil { tx.Rollback() return err } return nil } func (e *Entry) populateTags() error { q := `select name from tags where entry_id = ?` err := e.db.Select(&e.Tags, q, e.ID) log.Debug().Interface("entry", e).Msg("populating tags") return err } func (e *Entry) Update() error { if e.ID == -1 { return e.Create() } q := `update entries set slug=?, content=?, updated=?, author_id=? where id=?` _, err := e.db.Exec(q, e.Slug, e.Content, e.Updated.Unix(), e.AuthorID, e.ID) return err } func (e *Entry) Create() error { if e.ID != -1 { return e.Update() } tx, err := e.db.Begin() if err != nil { return err } q := `insert into entries (slug,content,created,updated,author_id) values (?,?,?,?,?)` res, err := tx.Exec(q, e.Slug, e.Content, e.Created.Unix(), e.Updated.Unix(), e.AuthorID) if err != nil { return err } e.ID, err = res.LastInsertId() if err != nil { tx.Rollback() e.ID = -1 return err } for _, t := range e.Tags { q = `insert into tags (name,entry_id) values (?,?)` _, err = tx.Exec(q, t, e.ID) if err != nil { tx.Rollback() return err } } tx.Commit() return nil }