mlisting

Mailing list service

git clone git://git.lin.moe/go/mlisting.git

  1package sqlite
  2
  3import (
  4	"context"
  5	"database/sql"
  6
  7	"git.lin.moe/go/mlisting/storage"
  8	_ "github.com/mattn/go-sqlite3"
  9)
 10
 11type Storage struct {
 12	*sql.DB
 13}
 14
 15func NewStorage(dsn string) (*Storage, error) {
 16	db, err := sql.Open("sqlite3", dsn)
 17	if err != nil {
 18		return nil, err
 19	}
 20	ctx, cancel := context.WithCancel(context.TODO())
 21	defer cancel()
 22
 23	if err := migrate(ctx, db); err != nil {
 24		return nil, err
 25	}
 26
 27	return &Storage{
 28		DB: db,
 29	}, nil
 30}
 31
 32func (s *Storage) GetList(ctx context.Context, address string) (storage.List, error) {
 33	const _sql = `select address, name, create_at, description, default_perm
 34                      from list where address=?`
 35	list := new(List)
 36	list.db = s.DB
 37
 38	row := s.DB.QueryRowContext(ctx, _sql, address)
 39	if err := row.Scan(
 40		&list.address,
 41		&list.name,
 42		&list.create_at,
 43		&list.description,
 44		&list.default_perm); err != nil {
 45		return nil, err
 46	}
 47	return list, nil
 48}
 49func (s *Storage) Lists(ctx context.Context) ([]storage.List, error) {
 50	const _sql = `SELECT address, name, create_at, description, default_perm FROM list`
 51	rows, err := s.DB.QueryContext(ctx, _sql)
 52	if err != nil {
 53		return nil, err
 54	}
 55	defer rows.Close()
 56
 57	lists := []storage.List{}
 58	for rows.Next() {
 59		list := new(List)
 60		list.db = s.DB
 61		if err := rows.Scan(
 62			&list.address,
 63			&list.name,
 64			&list.create_at,
 65			&list.description,
 66			&list.default_perm); err != nil {
 67			return nil, err
 68		}
 69		lists = append(lists, list)
 70	}
 71	return lists, nil
 72}
 73
 74func (s *Storage) NewList(ctx context.Context, name, address, description string, perm uint8) (storage.List, error) {
 75	const _sql = `insert into
 76                      list (name, address, description, default_perm)
 77                      values (?, ?, ?, ?)
 78                      returning name, address, create_at, description, default_perm`
 79	list := new(List)
 80	list.db = s.DB
 81
 82	row := s.DB.QueryRowContext(ctx, _sql, name, address, description, perm)
 83
 84	if err := row.Scan(
 85		&list.name,
 86		&list.address,
 87		&list.create_at,
 88		&list.description,
 89		&list.default_perm); err != nil {
 90		return nil, err
 91	}
 92	return list, nil
 93}
 94
 95func (s *Storage) UpdateList(ctx context.Context, address string, name, description string, defaultPerm uint8) (storage.List, error) {
 96	var i int
 97	if err := s.DB.QueryRowContext(ctx, "SELECT 1 from list where address=?", address).Scan(&i); err != nil {
 98		return nil, err
 99	}
100	const _sql = "UPDATE list SET name=?, description=?, default_perm=? WHERE address=? RETURNING address, name, create_at, description, default_perm"
101	var list = new(List)
102	row := s.DB.QueryRowContext(ctx, _sql, name, description, defaultPerm, address)
103	if err := row.Scan(&list.address, &list.name, &list.create_at, &list.description, &list.default_perm); err != nil {
104		return nil, err
105	}
106	list.db = s.DB
107	return list, nil
108}
109
110func (s *Storage) DeleteList(ctx context.Context, address string) error {
111	var err error
112
113	tx, err := s.DB.BeginTx(ctx, nil)
114	if err != nil {
115		return err
116	}
117
118	_, err = tx.ExecContext(ctx, `DELETE FROM member WHERE list=?`, address)
119	if err != nil {
120		tx.Rollback()
121		return err
122	}
123
124	_, err = tx.ExecContext(ctx, `DELETE FROM list WHERE address=?`, address)
125	if err != nil {
126		tx.Rollback()
127		return err
128	}
129	return tx.Commit()
130}
131
132func (s *Storage) Shutdown(context.Context) error {
133	return s.DB.Close()
134}