Files
simpleorm/ormexec.go
T
gdulai 01336bb911
Go Tests / test (push) Failing after 6s
Implement DML func and related tests
2026-05-04 21:33:29 +02:00

192 lines
4.0 KiB
Go

package simpleorm
import (
"database/sql"
"errors"
"reflect"
log "gitlab.com/gdulai/simpleloglvl"
)
type ORMExec[T any] struct {
orm *ORM
conn *DBConnection
}
func CreateExecution[T any](orm *ORM, conn *DBConnection) ORMExec[T] {
return ORMExec[T]{orm: orm, conn: conn}
}
func InitDB(conn *DBConnection, orm *ORM) {
// Force a real DB interaction
if _, err := conn.db.Exec(orm.CreateDDL()); err != nil {
log.LogFatalError("%", err)
}
}
func (ormExec ORMExec[T]) Select(desc T, whereStmt string, args ...any) ([]T, error) {
lookup := reflect.TypeOf(desc).Name()
table, ok := ormExec.orm.cache.Get(lookup)
if !ok {
return []T{}, errors.New("Failed to get descriptor from cache! " + lookup)
}
sqlStr := table.ToSelectDML()
if whereStmt != "" {
sqlStr += " WHERE " + whereStmt
}
log.LogDebug("Preparing sql: %s, with args: %s", sqlStr, args)
stmt, err := ormExec.conn.db.Prepare(sqlStr)
if err != nil {
return nil, err
}
defer stmt.Close()
log.LogDebug("Executing statement: %s", stmt)
var rows *sql.Rows
if len(args) == 0 {
rows, err = stmt.Query()
} else {
// Flattent args to make sure it can be parsed correctly
var flatArgs []any
for _, a := range args {
if s, ok := a.([]any); ok {
flatArgs = append(flatArgs, s...)
} else {
flatArgs = append(flatArgs, a)
}
}
rows, err = stmt.Query(flatArgs...)
}
if err != nil {
return nil, err
}
rowContainer := table.createSelectResultContainer()
var results []T
for rows.Next() {
err = rows.Scan(rowContainer...)
if err != nil {
return nil, err
}
targetType := table.Type
parsedResult := reflect.New(targetType)
for i, fieldVal := range rowContainer {
parsedResult.Elem().Field(i).Set(reflect.Indirect(reflect.ValueOf(fieldVal)))
}
parsedObj := reflect.Indirect(parsedResult).Interface().(T)
results = append(results, parsedObj)
}
return results, nil
}
func (ormExec ORMExec[T]) Insert(src ...T) error {
typeName := reflect.TypeOf(src[0]).Name()
table, ok := ormExec.orm.cache.Get(typeName)
if !ok {
return errors.New("Could not find table for type " + typeName)
}
sql := table.ToInsertDML(len(src))
var params []any
for i := range len(src) {
actualParams := table.prepareParams(src[i])
if len(params) == 0 {
params = make([]any, len(src)*len(actualParams))
}
for j := range actualParams {
params[(i*len(actualParams))+j] = actualParams[j]
}
}
log.LogInfo("%s [%s]", sql, params)
stmt, err := ormExec.conn.db.Prepare(sql)
if err != nil {
return err
}
defer stmt.Close()
result, err := stmt.Exec(params...)
if err != nil {
return err
} else {
rowsAffected, _ := result.RowsAffected()
log.LogInfo("Inserted %s row", rowsAffected)
}
return nil
}
func (ormExec ORMExec[T]) Update(src T) error {
typeName := reflect.TypeOf(src).Name()
table, ok := ormExec.orm.cache.Get(reflect.TypeOf(src).Name())
if !ok {
return errors.New("Could not find table for type " + typeName)
}
sql := table.ToUpdateDML(src)
params := table.prepareParams(src)
pk, err := table.getPk(src)
if err != nil {
return err
}
// Put the pk back at the end
params = append(params, pk)
log.LogInfo("%s [%s]", sql, params)
stmt, err := ormExec.conn.db.Prepare(sql)
if err != nil {
return err
}
defer stmt.Close()
result, err := stmt.Exec(params...)
if err != nil {
return err
} else {
rowsAffected, _ := result.RowsAffected()
log.LogInfo("Updated %s row", rowsAffected)
}
return nil
}
func (ormExec ORMExec[T]) Delete(src T) error {
typeName := reflect.TypeOf(src).Name()
table, ok := ormExec.orm.cache.Get(reflect.TypeOf(src).Name())
if !ok {
return errors.New("Could not find table for type " + typeName)
}
sql := table.ToDeleteDML(src)
pk, err := table.getPk(src)
if err != nil {
return err
}
log.LogInfo("%s [%s]", sql, pk)
stmt, err := ormExec.conn.db.Prepare(sql)
if err != nil {
return err
}
defer stmt.Close()
result, err := stmt.Exec(pk)
if err != nil {
return err
} else {
rowsAffected, _ := result.RowsAffected()
log.LogInfo("Deleted %s row", rowsAffected)
}
return nil
}