maddy/internal/table/sql.go
2020-02-29 19:23:28 +03:00

89 lines
1.7 KiB
Go

package table
import (
"database/sql"
"strings"
"github.com/foxcpp/maddy/internal/config"
"github.com/foxcpp/maddy/internal/module"
_ "github.com/lib/pq"
)
type SQL struct {
modName string
instName string
db *sql.DB
lookup *sql.Stmt
}
func NewSQL(modName, instName string, _, _ []string) (module.Module, error) {
return &SQL{
modName: modName,
instName: instName,
}, nil
}
func (s *SQL) Name() string {
return s.modName
}
func (s *SQL) InstanceName() string {
return s.instName
}
func (s *SQL) Init(cfg *config.Map) error {
var (
driver string
initQueries []string
dsnParts []string
lookupQuery string
)
cfg.StringList("init", false, false, nil, &initQueries)
cfg.String("driver", false, true, "", &driver)
cfg.StringList("dsn", false, true, nil, &dsnParts)
cfg.String("lookup", false, true, "", &lookupQuery)
if _, err := cfg.Process(); err != nil {
return err
}
db, err := sql.Open(driver, strings.Join(dsnParts, " "))
if err != nil {
return config.NodeErr(cfg.Block, "failed to open db: %v", err)
}
s.db = db
for _, init := range initQueries {
if _, err := db.Exec(init); err != nil {
return config.NodeErr(cfg.Block, "init query failed: %v", err)
}
}
s.lookup, err = db.Prepare(lookupQuery)
if err != nil {
return config.NodeErr(cfg.Block, "failed to prepare lookup query: %v", err)
}
return nil
}
func (s *SQL) Close() error {
s.lookup.Close()
return s.db.Close()
}
func (s *SQL) Lookup(val string) (string, bool, error) {
var repl string
row := s.lookup.QueryRow(val)
if err := row.Scan(&repl); err != nil {
if err == sql.ErrNoRows {
return "", false, nil
}
return "", false, err
}
return repl, true, nil
}
func init() {
module.Register("sql_table", NewSQL)
}