func (db *Database) GetByID(id int) (*Todo, error) {
	todo := &Todo{}
	err := db.db.QueryRow(stmtSelectByID, id).Scan(&todo.ID, &todo.MemberID, &todo.Created, &todo.Detail, &todo.Completed)
	switch {
	case err == sql.ErrNoRows:
		return nil, ErrTodoNotFound
	case err != nil:
		return nil, err
	}
	return todo, nil
}
GetByID retrieves a todo by its ID.
package todos
import (
	"database/sql"
	"fmt"
	"time"
)
type Database struct {
	db *sql.DB
}
func New(db *sql.DB) *Database {
	return &Database{
		db: db,
	}
}
type Todo struct {
	ID        int       `json:"id"`
	MemberID  int       `json:"member_id"`
	Created   time.Time `json:"created"`
	Detail    string    `json:"detail"`
	Completed bool      `json:"completed"`
}
type Todos struct {
	Todos []*Todo `json:"todos"`
	Total int     `json:"total"`
}
const (
	stmtInsert = `
INSERT INTO todos (member_id, created, detail, completed)
VALUES (?, ?, ?, ?)
`
	stmtSelect = `
SELECT id, member_id, created, detail, completed
FROM todos
%s
LIMIT %v, %v
`
	stmtSelectCount = `
SELECT COUNT(*)
FROM todos
%s
`
	stmtSelectByID = `
SELECT id, member_id, created, detail, completed
FROM todos
WHERE id=?
`
	stmtSelectByIDAndMemberID = `
SELECT id, member_id, created, detail, completed
FROM todos
WHERE id=? AND member_id=?
`
	stmtUpdate = `
UPDATE todos
SET %s
WHERE id=?
`
)
type NewParams struct {
	Detail string `json:"detail"`
}
func (db *Database) New(mid int, params *NewParams) (*Todo, error) {
	todo := &Todo{
		MemberID: mid,
		Created:  time.Now(),
		Detail:   params.Detail,
	}
	var res sql.Result
	var err error
	if res, err = db.db.Exec(stmtInsert, todo.MemberID, todo.Created, todo.Detail, todo.Completed); err != nil {
		return nil, err
	}
	id, err := res.LastInsertId()
	if err != nil {
		return nil, err
	}
	todo.ID = int(id)
	return todo, nil
}
type GetParams struct {
	ID        *int       `json:"id"`
	MemberID  *int       `json:"member_id"`
	Created   *time.Time `json:"created"`
	Completed *bool      `json:"completed"`
	Offset    int        `json:"offset"`
	Limit     int        `json:"limit"`
}
func (db *Database) Get(params *GetParams) (*Todos, error) {
	var queryFields string
	var queryValues []interface{}
	if params.ID != nil {
		if queryFields == "" {
			queryFields = "WHERE id=?"
		} else {
			queryFields += " AND id=?"
		}
		queryValues = append(queryValues, *params.ID)
	}
	if params.MemberID != nil {
		if queryFields == "" {
			queryFields = "WHERE member_id=?"
		} else {
			queryFields += " AND member_id=?"
		}
		queryValues = append(queryValues, *params.MemberID)
	}
	if params.Created != nil {
		if queryFields == "" {
			queryFields = "WHERE created=?"
		} else {
			queryFields += " AND created=?"
		}
		queryValues = append(queryValues, *params.Created)
	}
	if params.Completed != nil {
		if queryFields == "" {
			queryFields = "WHERE completed=?"
		} else {
			queryFields += " AND completed=?"
		}
		queryValues = append(queryValues, *params.Created)
	}
	query := fmt.Sprintf(stmtSelect, queryFields, params.Offset, params.Limit)
	todos := &Todos{
		Todos: []*Todo{},
	}
	rows, err := db.db.Query(query, queryValues...)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	for rows.Next() {
		todo := &Todo{}
		if err := rows.Scan(&todo.ID, &todo.MemberID, &todo.Created, &todo.Detail, &todo.Completed); err != nil {
			return nil, err
		}
		todos.Todos = append(todos.Todos, todo)
	}
	if err = rows.Err(); err != nil {
		return nil, err
	}
	queryCount := fmt.Sprintf(stmtSelectCount, queryFields)
	var total int
	if err = db.db.QueryRow(queryCount, queryValues...).Scan(&total); err != nil {
		return nil, err
	}
	todos.Total = total
	return todos, nil
}