83 lines
1.7 KiB
Go

package database
import (
"fmt"
"strings"
)
// Trackable interface for models that can track field changes
type Trackable interface {
GetTableName() string
GetID() int
GetDirtyFields() map[string]any
SetDirty(field string, value any)
ClearDirty()
IsDirty() bool
}
// FieldTracker provides dirty field tracking functionality
type FieldTracker struct {
dirty map[string]any
}
// SetDirty marks a field as dirty with its new value
func (ft *FieldTracker) SetDirty(field string, value any) {
if ft.dirty == nil {
ft.dirty = make(map[string]any)
}
ft.dirty[field] = value
}
// GetDirtyFields returns map of dirty fields and their values
func (ft *FieldTracker) GetDirtyFields() map[string]any {
if ft.dirty == nil {
return make(map[string]any)
}
return ft.dirty
}
// ClearDirty clears all dirty field tracking
func (ft *FieldTracker) ClearDirty() {
ft.dirty = nil
}
// IsDirty returns true if any fields have been modified
func (ft *FieldTracker) IsDirty() bool {
return len(ft.dirty) > 0
}
// UpdateDirty updates only dirty fields in the database
func UpdateDirty(model Trackable) error {
if !model.IsDirty() {
return nil // No changes to save
}
dirty := model.GetDirtyFields()
if len(dirty) == 0 {
return nil
}
// Build dynamic UPDATE query
var setParts []string
var args []any
for field, value := range dirty {
setParts = append(setParts, field+" = ?")
args = append(args, value)
}
args = append(args, model.GetID()) // Add ID for WHERE clause
query := fmt.Sprintf("UPDATE %s SET %s WHERE id = ?",
model.GetTableName(),
strings.Join(setParts, ", "))
err := Exec(query, args...)
if err != nil {
return fmt.Errorf("failed to update %s: %w", model.GetTableName(), err)
}
model.ClearDirty()
return nil
}