package sqimple import ( "context" "database/sql" "slices" "strings" ) // https://www.sqlite.org/lang_update.html type UpdateStatement struct { Ctx context.Context DB *sql.DB table UpdateTable or string columns []string set map[string]any where []Where args []any } func (s *UpdateStatement) Args() []any { args := []any{} for _, column := range s.columns { args = append(args, s.set[column]) } for _, arg := range s.args { args = append(args, arg) } return args } func (s *UpdateStatement) Exec() (sql.Result, error) { if s.DB != nil { if s.Ctx != nil { return s.DB.ExecContext(s.Ctx, s.String(), s.Args()...) } return s.DB.Exec(s.String(), s.Args()...) } return nil, ErrNoDatabase } func (s *UpdateStatement) IsValid() bool { if !s.table.IsValid() { return false } for _, w := range s.where { if !w.IsValid() { return false } } return false } func (s *UpdateStatement) Or(or string) *UpdateStatement { s.or = or return s } func (s *UpdateStatement) Set(column string, value any) *UpdateStatement { if s.columns == nil { s.columns = []string{} } if s.set == nil { s.set = map[string]any{} } if !slices.Contains(s.columns, column) { s.columns = append(s.columns, column) } s.set[column] = value return s } func (s *UpdateStatement) SetMap(data map[string]any) *UpdateStatement { for column, value := range data { s.Set(column, value) } return s } func (s *UpdateStatement) String() string { strs := []string{"update"} if s.or != "" { strs = append(strs, "or", s.or) } strs = append(strs, s.table.String(), "set") for i, column := range s.columns { if i < len(s.columns)-1 { strs = append(strs, column, "= ?,") } else { strs = append(strs, column, "= ?") } } if len(s.where) > 0 { strs = append(strs, "where") for _, w := range s.where { strs = append(strs, w.String()) } } return strings.Join(strs, " ") } func (s *UpdateStatement) Where(def string, args ...any) *UpdateStatement { s.where = append(s.where, Where(def)) if len(args) > 0 { if s.args == nil { s.args = []any{} } s.args = append(s.args, args...) } return s } func Update(table string) *UpdateStatement { s := &UpdateStatement{ table: UpdateTable(table), } return s }