This commit continues removing the environment abstraction and removes all 'net' related functions, replacing them by their native equivalents.
122 lines
2.7 KiB
Go
122 lines
2.7 KiB
Go
package sql
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"fmt"
|
|
"time"
|
|
|
|
"gorm.io/driver/mysql"
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/logger"
|
|
|
|
"github.com/FAU-CDI/wisski-distillery/internal/dis/component"
|
|
"github.com/FAU-CDI/wisski-distillery/internal/models"
|
|
"github.com/tkw1536/pkglib/timex"
|
|
)
|
|
|
|
//
|
|
// ========== low-level connection ==========
|
|
//
|
|
|
|
// Exec executes a database-independent database query.
|
|
func (sql *SQL) Exec(query string, args ...interface{}) error {
|
|
// connect to the server
|
|
conn, err := sql.connect("")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// do the query!
|
|
{
|
|
_, err := conn.Exec(query, args...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
//
|
|
// ========== connection via gorm ==========
|
|
//
|
|
|
|
// QueryTable returns a gorm.DB to connect to the provided table of the given model
|
|
func (sql *SQL) QueryTable(ctx context.Context, table component.Table) (*gorm.DB, error) {
|
|
return sql.queryTable(ctx, false, table.TableInfo().Name)
|
|
}
|
|
|
|
// queryTable returns a gorm.DB to connect to the provided distillery database table
|
|
func (sql *SQL) queryTable(ctx context.Context, silent bool, table string) (*gorm.DB, error) {
|
|
conn, err := sql.connect(sql.Config.SQL.Database)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// gorm configuration
|
|
config := &gorm.Config{
|
|
Logger: newGormLogger(),
|
|
}
|
|
if silent {
|
|
config.Logger = config.Logger.LogMode(logger.Silent)
|
|
} else {
|
|
config.Logger = config.Logger.LogMode(logger.Info)
|
|
}
|
|
|
|
// mysql connection
|
|
cfg := mysql.Config{
|
|
Conn: conn,
|
|
|
|
DefaultStringSize: 256,
|
|
}
|
|
|
|
// open the gorm connection!
|
|
db, err := gorm.Open(mysql.New(cfg), config)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// set the table
|
|
db = db.WithContext(ctx).Table(table)
|
|
|
|
// check that nothing went wrong
|
|
if db.Error != nil {
|
|
return nil, db.Error
|
|
}
|
|
return db, nil
|
|
}
|
|
|
|
// WaitQueryTable waits for a connection to succeed via QueryTable
|
|
func (sql *SQL) WaitQueryTable(ctx context.Context) error {
|
|
// TODO: Establish a convention on when to wait for this!
|
|
return timex.TickUntilFunc(func(time.Time) bool {
|
|
// TODO: Use a different table here
|
|
_, err := sql.queryTable(ctx, true, models.InstanceTable)
|
|
return err == nil
|
|
}, ctx, sql.PollInterval)
|
|
}
|
|
|
|
//
|
|
// ========== low-level database connection ==========
|
|
//
|
|
|
|
func (ssql *SQL) connect(database string) (*sql.DB, error) {
|
|
conn, err := sql.Open("mysql", ssql.dsn(database))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
conn.SetMaxIdleConns(0)
|
|
|
|
return conn, nil
|
|
}
|
|
|
|
// dsn returns a dsn fof connecting to the database
|
|
func (sql *SQL) dsn(database string) string {
|
|
user := sql.Config.SQL.AdminUsername
|
|
pass := sql.Config.SQL.AdminPassword
|
|
network := "tcp"
|
|
server := sql.ServerURL
|
|
|
|
return fmt.Sprintf("%s:%s@%s(%s)/%s?charset=utf8&parseTime=True&loc=Local", user, pass, network, server, database)
|
|
}
|