turso-maddy/table/turso.go

206 lines
3.9 KiB
Go
Raw Normal View History

2024-04-02 20:15:11 -06:00
package table
import (
"context"
"database/sql"
"fmt"
"log"
"os"
"github.com/foxcpp/maddy/framework/config"
"github.com/foxcpp/maddy/framework/module"
"github.com/tursodatabase/go-libsql"
2024-04-06 18:40:10 -06:00
_ "github.com/tursodatabase/libsql-client-go/libsql"
2024-04-02 20:15:11 -06:00
)
2024-04-06 18:40:10 -06:00
type table struct {
2024-04-02 20:15:11 -06:00
modName string
instName string
lookup string
add string
list string
set string
del string
dir string
sql *sql.DB
connector *libsql.Connector
}
func NewTable(modName, instName string, _, _ []string) (module.Module, error) {
2024-04-06 18:40:10 -06:00
return &table{
2024-04-02 20:15:11 -06:00
modName: modName,
instName: instName,
}, nil
}
2024-04-06 18:40:10 -06:00
func (s *table) Name() string {
2024-04-02 20:15:11 -06:00
return s.modName
}
2024-04-06 18:40:10 -06:00
func (s *table) InstanceName() string {
2024-04-02 20:15:11 -06:00
return s.instName
}
2024-04-06 18:40:10 -06:00
func (s *table) Init(cfg *config.Map) error {
2024-04-02 20:15:11 -06:00
var (
initQueries []string
primaryUrl string
)
cfg.StringList("init", false, false, nil, &initQueries)
cfg.String("url", false, true, "", &primaryUrl)
cfg.String("lookup", false, true, "", &s.lookup)
cfg.String("add", false, false, "", &s.add)
cfg.String("list", false, false, "", &s.list)
cfg.String("del", false, false, "", &s.del)
cfg.String("set", false, false, "", &s.set)
if _, err := cfg.Process(); err != nil {
return err
}
var err error
2024-04-06 18:40:10 -06:00
s.sql, err = sql.Open("libsql", primaryUrl)
2024-04-02 20:15:11 -06:00
if len(initQueries) > 0 {
tx, err := s.sql.Begin()
if err != nil {
return err
}
for _, qry := range initQueries {
res, err := tx.Exec(qry)
if err != nil {
return err
}
rows, err := res.RowsAffected()
log.Println("db rows effected: ", rows, err)
}
if err = tx.Commit(); err != nil {
return err
}
}
2024-04-06 18:40:10 -06:00
return err
2024-04-02 20:15:11 -06:00
}
2024-04-06 18:40:10 -06:00
func (s *table) Close() error {
2024-04-02 20:15:11 -06:00
defer os.RemoveAll(s.dir)
defer s.connector.Close()
return s.sql.Close()
}
2024-04-06 18:40:10 -06:00
func (s *table) Lookup(ctx context.Context, val string) (value string, ok bool, err error) {
2024-04-02 20:15:11 -06:00
defer func() {
if err != nil {
err = fmt.Errorf("%s: lookup: %w", s.modName, err)
}
}()
row := s.sql.QueryRowContext(ctx, s.lookup, val)
err = row.Scan(&value)
return value, err == nil, err
}
2024-04-06 18:40:10 -06:00
func (s *table) LookupMulti(ctx context.Context, val string) (lis []string, err error) {
2024-04-02 20:15:11 -06:00
defer func() {
if err != nil {
err = fmt.Errorf("%s: lookupMulti: %w", s.modName, err)
}
}()
var rows *sql.Rows
rows, err = s.sql.QueryContext(ctx, s.lookup, val)
if err != nil {
return
}
defer rows.Close()
for rows.Next() {
var value string
err = rows.Scan(&value)
if err != nil {
return
}
lis = append(lis, value)
}
err = rows.Err()
return
}
2024-04-06 18:40:10 -06:00
func (s *table) Keys() (lis []string, err error) {
2024-04-02 20:15:11 -06:00
if s.list == "" {
return nil, fmt.Errorf("%s: table is not mutable (no 'list' query)", s.modName)
}
defer func() {
if err != nil {
err = fmt.Errorf("%s: list: %w", s.modName, err)
}
}()
var rows *sql.Rows
rows, err = s.sql.Query(s.list)
if err != nil {
return
}
defer rows.Close()
for rows.Next() {
var value string
err = rows.Scan(&value)
if err != nil {
return
}
lis = append(lis, value)
}
err = rows.Err()
return
}
2024-04-06 18:40:10 -06:00
func (s *table) RemoveKey(k string) (err error) {
2024-04-02 20:15:11 -06:00
if s.del == "" {
return fmt.Errorf("%s: table is not mutable (no 'del' query)", s.modName)
}
_, err = s.sql.ExecContext(context.TODO(), s.del, k)
if err != nil {
return fmt.Errorf("%s: del %s: %w", s.modName, k, err)
}
return nil
}
2024-04-06 18:40:10 -06:00
func (s *table) SetKey(k, v string) (err error) {
2024-04-02 20:15:11 -06:00
if s.set == "" {
return fmt.Errorf("%s: table is not mutable (no 'set' query)", s.modName)
}
if s.add == "" {
return fmt.Errorf("%s: table is not mutable (no 'add' query)", s.modName)
}
res, err := s.sql.ExecContext(context.TODO(), s.set, k, v)
if err != nil {
return fmt.Errorf("%s: set %s: %w", s.modName, k, err)
}
2024-04-06 18:40:10 -06:00
var n int64
if n, err = res.RowsAffected(); err != nil && n == 0 {
_, err = s.sql.ExecContext(context.TODO(), s.add, k, v)
if err != nil {
return fmt.Errorf("%s: add %s: %w", s.modName, k, err)
2024-04-02 20:15:11 -06:00
}
2024-04-06 18:40:10 -06:00
}
2024-04-02 20:15:11 -06:00
return
}
func init() {
module.Register("table.turso_query", NewTable)
}