From 7bd3c333fe5ee70a921f832cc71500e7c7451af6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C5=91=20Dulai?= Date: Mon, 11 May 2026 00:12:41 +0200 Subject: [PATCH] WIP: Refactor - delete dml --- exec/exec.go | 56 +++++++++++++++++++++++++++++++++++++++++++- exec_test.go | 61 ++++++++++++++++++++++++++++++++++++++++++++++++ schema/schema.go | 4 ++-- schema/table.go | 26 ++++++++++++++++----- 4 files changed, 138 insertions(+), 9 deletions(-) diff --git a/exec/exec.go b/exec/exec.go index ddd3c26..56ac02d 100644 --- a/exec/exec.go +++ b/exec/exec.go @@ -172,7 +172,7 @@ func NewUpdate[T any](orm *simpleorm.ORM, toUpdate T) (Update[T], error) { } func (u Update[T]) Execute(conn *simpleorm.DBConnection) ([]T, error) { - dml, err := u.target.GetUpdateDML(u.toUpdate) + dml, err := u.target.GetUpdateDML() if err != nil { return []T{}, err } @@ -206,6 +206,60 @@ func (u Update[T]) Execute(conn *simpleorm.DBConnection) ([]T, error) { return []T{u.toUpdate}, nil } +type Delete[T any] struct { + target schema.Table + toDelete []T +} + +func NewDelete[T any](orm *simpleorm.ORM, toDelete []T) (Delete[T], error) { + table, ok := orm.Cache().Get(reflect.TypeFor[T]().Name()) + if !ok { + return Delete[T]{}, errors.New("Failed to get table from schema cache") + } + + return Delete[T]{target: *table, toDelete: toDelete}, nil +} + +func (d Delete[T]) Execute(conn *simpleorm.DBConnection) ([]T, error) { + count := len(d.toDelete) + dml, err := d.target.GetDeleteDML(count) + if err != nil { + return []T{}, err + } + + var params []any + + for _, del := range d.toDelete { + pkCols, err := getPk(del, d.target) + if err != nil { + return []T{}, err + } + + for _, pk := range pkCols { + params = append(params, pk) + } + } + + log.LogInfo("%s [%s]", dml, params) + + stmt, err := conn.Prepare(dml) + if err != nil { + return []T{}, err + } + defer stmt.Close() + + result, err := stmt.Exec(params...) + if err != nil { + return []T{}, err + } else { + rowsAffected, _ := result.RowsAffected() + log.LogInfo("Deleted %s row", rowsAffected) + } + + return d.toDelete, nil + +} + func createSelectResultContainer(t schema.Table) []any { vals := make([]any, t.Type.NumField()) for i := range vals { diff --git a/exec_test.go b/exec_test.go index 5cbf2c6..de5a969 100644 --- a/exec_test.go +++ b/exec_test.go @@ -258,3 +258,64 @@ func TestInsertAndUpdate(t *testing.T) { } } + +func TestInsertAndDelete(t *testing.T) { + // GIVEN + conn := simpleorm.OpenConnection("sqlite3", "file:test.db") + defer cleanUp("test.db", conn) + orm := simpleorm.NewORM(Test{}, TestWithFk{}, TestWithFkAndFkId{}, + TestWithCompositePk{}, TestWithCompositeFk{}) + + exec.ExecuteDDL(conn, orm) + + testObj := Test{Int64Field: 54, IntField: 12, StringField: "asdf"} + + insertExec, err := exec.NewInsert(orm, testObj) + if err != nil { + log.LogError("TestInsertAndDelete setup failed: %s", err) + t.Fail() + return + } + + _, err = insertExec.Execute(conn) + if err != nil { + log.LogError("TestInsertAndDelete setup failed: %s", err) + t.Fail() + return + } + + selectExec, err := exec.CreateSelect[Test](orm, "") + if err != nil { + log.LogError("TestInsertAndDelete setup failed: %s", err) + t.Fail() + return + } + + selectRes, err := selectExec.Execute(conn) + + if err != nil { + log.LogError("TestInsertAndDelete setup failed. %s", err) + t.Fail() + return + } + + deleteExec, err := exec.NewDelete[Test](orm, selectRes) + + // WHEN + _, err = deleteExec.Execute(conn) + + // THEN + if err != nil { + log.LogError("TestInsertAndDelete delete failure. %s", err) + t.Fail() + return + } + + selectRes, err = selectExec.Execute(conn) + if len(selectRes) != 0 { + log.LogError("TestInsertAndDelete test failed. Expected: 0, Actual: %s", len(selectRes)) + t.Fail() + return + } + +} diff --git a/schema/schema.go b/schema/schema.go index 24ba948..e698665 100644 --- a/schema/schema.go +++ b/schema/schema.go @@ -5,7 +5,7 @@ package schema type SchemaDescriptor interface { getDDL() (string, error) GetSelectDML() (string, error) - GetInsertDML() (string, error) + GetInsertDML(count int) (string, error) GetUpdateDML() (string, error) - GetDeleteDML() (string, error) + GetDeleteDML(count int) (string, error) } diff --git a/schema/table.go b/schema/table.go index e460a09..76bd660 100644 --- a/schema/table.go +++ b/schema/table.go @@ -1,7 +1,6 @@ package schema import ( - "errors" "reflect" "strings" @@ -104,7 +103,7 @@ func (t Table) GetInsertDML(count int) (string, error) { return dml.String(), nil } -func (t Table) GetUpdateDML(src any) (string, error) { +func (t Table) GetUpdateDML() (string, error) { var dml strings.Builder dml.WriteString("UPDATE " + util.CamelToSnake(t.Type.Name()) + " SET ") @@ -145,18 +144,33 @@ func (t Table) GetUpdateDML(src any) (string, error) { return dml.String(), nil } -func (t Table) GetDeleteDML(src any) (string, error) { +func (t Table) GetDeleteDML(count int) (string, error) { var dml strings.Builder dml.WriteString("DELETE FROM " + t.Name + " WHERE ") + for _, col := range t.Columns { modifiers := col.Modifiers _, ok := modifiers["pk"] if ok { - dml.WriteString(col.Name + " = ?") - return dml.String(), nil + if count > 1 { + dml.WriteString(col.Name + " IN (") + } else { + dml.WriteString(col.Name + " = ") + } } } - return "", errors.New("Failed to determine primar key column for delete dml.") + for i := range count { + if i != 0 { + dml.WriteString(", ") + } + dml.WriteString("?") + } + + if count > 1 { + dml.WriteString(")") + } + + return dml.String(), nil }