blob: 1b2f265cc112123a5c3f210bc3ec24350d9b6b87 [file] [log] [blame]
// compile -G=3
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"database/sql"
)
// Collection generic interface which things can be added to.
type Collection[T any] interface {
Add(T)
}
// Slice generic slice implementation of a Collection
type Slice[T any] []*T
func (s *Slice[T]) Add(t *T) {
*s = append(*s, t)
}
type Scanner interface {
Scan(...interface{}) error
}
type Mapper[T any] func(s Scanner, t T) error
type Repository[T any] struct {
db *sql.DB
}
func (r *Repository[T]) scan(rows *sql.Rows, m Mapper[*T], c Collection[*T]) error {
for rows.Next() {
t := new(T)
if err := m(rows, t); err != nil {
return err
}
c.Add(t)
}
return rows.Err()
}
func (r *Repository[T]) query(query string, m Mapper[*T], c Collection[*T]) error {
rows, err := r.db.Query(query)
if err != nil {
return err
}
if err := r.scan(rows, m, c); err != nil {
rows.Close()
return err
}
return rows.Close()
}
type Actor struct {
ActorID uint16
FirstName string
LastName string
}
type ActorRepository struct {
r Repository[Actor]
}
func (ActorRepository) scan(s Scanner, a *Actor) error {
return s.Scan(&a.ActorID, &a.FirstName, &a.LastName)
}
func (r *ActorRepository) SelectAll(c Collection[*Actor]) error {
return r.r.query("SELECT `actor_id`, `first_name`, `last_name` FROM `actor` LIMIT 10", r.scan, c)
}