gorm/chain.go

195 lines
3.9 KiB
Go

package gorm
import (
"database/sql"
"errors"
"fmt"
"regexp"
"strconv"
)
type Chain struct {
db *sql.DB
driver string
value interface{}
Errors []error
Error error
whereClause []map[string]interface{}
orClause []map[string]interface{}
selectStr string
orderStrs []string
offsetStr string
limitStr string
specifiedTableName string
}
func (s *Chain) err(err error) {
if err != nil {
s.Errors = append(s.Errors, err)
s.Error = err
}
}
func (s *Chain) do(value interface{}) *Do {
var do Do
do.chain = s
do.db = s.db
do.driver = s.driver
do.whereClause = s.whereClause
do.orClause = s.orClause
do.selectStr = s.selectStr
do.orderStrs = s.orderStrs
do.offsetStr = s.offsetStr
do.limitStr = s.limitStr
do.specifiedTableName = s.specifiedTableName
s.value = value
do.setModel(value)
return &do
}
func (s *Chain) Model(model interface{}) *Chain {
s.value = model
return s
}
func (s *Chain) Where(querystring interface{}, args ...interface{}) *Chain {
s.whereClause = append(s.whereClause, map[string]interface{}{"query": querystring, "args": args})
return s
}
func (s *Chain) Limit(value interface{}) *Chain {
switch value := value.(type) {
case string:
s.limitStr = value
case int:
if value < 0 {
s.limitStr = ""
} else {
s.limitStr = strconv.Itoa(value)
}
default:
s.err(errors.New("Can' understand the value of Limit, Should be int"))
}
return s
}
func (s *Chain) Offset(value interface{}) *Chain {
switch value := value.(type) {
case string:
s.offsetStr = value
case int:
if value < 0 {
s.offsetStr = ""
} else {
s.offsetStr = strconv.Itoa(value)
}
default:
s.err(errors.New("Can' understand the value of Offset, Should be int"))
}
return s
}
func (s *Chain) Order(value string, reorder ...bool) *Chain {
defer s.validSql(value)
if len(reorder) > 0 && reorder[0] {
s.orderStrs = append([]string{}, value)
} else {
s.orderStrs = append(s.orderStrs, value)
}
return s
}
func (s *Chain) Count(value interface{}) *Chain {
s.Select("count(*)").do(s.value).count(value)
return s
}
func (s *Chain) Select(value interface{}) *Chain {
defer func() { s.validSql(s.selectStr) }()
switch value := value.(type) {
case string:
s.selectStr = value
default:
s.err(errors.New("Can' understand the value of Select, Should be string"))
}
return s
}
func (s *Chain) Save(value interface{}) *Chain {
s.do(value).save()
return s
}
func (s *Chain) Delete(value interface{}) *Chain {
s.do(value).delete()
return s
}
func (s *Chain) Update(column string, value interface{}) *Chain {
return s.Updates(map[string]interface{}{column: value}, true)
}
func (s *Chain) Updates(values map[string]interface{}, ignore_protected_attrs ...interface{}) *Chain {
do := s.do(s.value)
do.updateAttrs = values
do.ignoreProtectedAttrs = len(ignore_protected_attrs) > 0
do.update()
return s
}
func (s *Chain) Exec(sql string) *Chain {
var err error
_, err = s.db.Exec(sql)
s.err(err)
return s
}
func (s *Chain) First(out interface{}, where ...interface{}) *Chain {
do := s.do(out)
do.limitStr = "1"
do.query(where...)
return s
}
func (s *Chain) Find(out interface{}, where ...interface{}) *Chain {
s.do(out).query(where...)
return s
}
func (s *Chain) Pluck(column string, value interface{}) (orm *Chain) {
do := s.do(s.value)
do.selectStr = column
do.pluck(value)
return s
}
func (s *Chain) Or(querystring interface{}, args ...interface{}) *Chain {
s.orClause = append(s.orClause, map[string]interface{}{"query": querystring, "args": args})
return s
}
func (s *Chain) CreateTable(value interface{}) *Chain {
s.do(value).createTable().exec()
return s
}
func (s *Chain) Table(name string) *Chain {
s.specifiedTableName = name
return s
}
func (s *Chain) validSql(str string) (result bool) {
result = regexp.MustCompile("^\\s*[\\w][\\w\\s,.]*[\\w]\\s*$").MatchString(str)
if !result {
s.err(errors.New(fmt.Sprintf("SQL is not valid, %s", str)))
}
return
}