package orm import ( "fmt" "reflect" "strings" "github.com/huandu/go-sqlbuilder" ) var SqlFlavor = sqlbuilder.MySQL type SqlType uint8 const ( Select SqlType = iota << 1 Update Insert Delete ) type cmethod uint8 type ctype uint8 const ( And ctype = iota Or Between NotBetween EqualThan NotEqualThan GreaterThan GreatenThanEqual LessThan LessThanEqual Like NotLike In NotIn Null NotNull ) const ( Limit cmethod = iota Where ) type Cond struct { Method cmethod Type ctype vars []interface{} } func (c Cond) SetVar(v ...interface{}) Cond { c.vars = append(c.vars, v...) return c } type selectBuilder struct { *sqlbuilder.SelectBuilder } func getSelectBuilder(tbl *table) *selectBuilder { return &selectBuilder{ sqlbuilder.NewSelectBuilder().From(tbl.getNameAs(true)), } } func (sb *selectBuilder) getXint64(v reflect.Value, unsigned bool) interface{} { switch v.Kind() { case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: if !unsigned { return int(v.Uint()) } return v.Uint() case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: if unsigned { return uint64(v.Int()) } return v.Int() } return 0 } func (sb *selectBuilder) _extra(tbl *table, extra ...Cond) *selectBuilder { for _, cond := range extra { if len(cond.vars) == 0 { continue } for i, v := range cond.vars { switch v.(type) { case string: if s := strings.SplitAfterN(v.(string), ".", 2); len(s) > 1 { fmt.Println(s, s[0][0:len(s[0])-1]) for _, rels := range tbl.getRelations() { for _, rel := range rels { if rel.f.getFieldName() == s[0][0:len(s[0])-1] { cond.vars[i] = sqlbuilder.Raw(rel.getAlias(true) + "." + SqlFlavor.Quote(s[1])) } } } cond.vars[i] = v } } } switch cond.Method { case Limit: if len(cond.vars) > 0 { switch cond.vars[0].(type) { case int, uint: sb.Limit(cond.vars[0].(int)) } } case Where: switch cond.Type { case Null: sb.Where(sb.IsNull(cond.vars[0].(string))) case NotNull: sb.Where(sb.IsNotNull(cond.vars[0].(string))) } } } //fmt.Println(sb) return sb } func (sb *selectBuilder) _select(tbls ...interface{}) *selectBuilder { cols := []string{} for _, tbl := range tbls { switch tbl.(type) { case relation: rtbl := tbl.(relation) for _, col := range rtbl.table.getColumns() { cols = append(cols, col.getName(true, rtbl)) } case *table: rtbl := tbl.(*table) for _, col := range rtbl.getColumns() { cols = append(cols, col.getName(true, rtbl)) } } } sb.Select(cols...) return sb } func (sb *selectBuilder) _where(tbl *table, i MappableInterface) *selectBuilder { tmp := tbl.Make() where := []string{} outerloop: for _, col := range tbl.getColumns() { fn := "Get" + strings.Title(col.getFieldName()) val, err := tbl.CallMethod(i, fn) if err == nil { tmpv, _ := tbl.CallMethod(tmp, fn) for i, v := range val { if v == tmpv[i] { continue outerloop } } fmt.Println(fn, val) where = append(where, sb.Equal(col.getName(true, tbl), val[0])) } else { fmt.Println(err) } } sb.Where(where...) return sb } func (sb *selectBuilder) _wherePrimaryOrElse(tbl *table, i MappableInterface) *selectBuilder { if pk := tbl.getPrimaryKey(); pk != nil { val, err := tbl.CallMethod(i, "Get"+strings.Title(pk.getFieldName())) if err != nil { sb._where(tbl, i) } else { sb.Where(sb.Equal(pk.getName(true, tbl), val[0])) } } else { sb._where(tbl, i) } return sb } func (sb *selectBuilder) _join(tbl *table, rel relation, opt ...sqlbuilder.JoinOption) *selectBuilder { if len(opt) == 0 { sb.Join(rel.getNameAs(true), sb.Equal(rel.on.getName(true, rel), sqlbuilder.Raw(rel.key.getName(true, tbl)))) } else { sb.JoinWithOption(opt[0], rel.getNameAs(true), sb.Equal(rel.on.getName(true, rel), sqlbuilder.Raw(rel.key.getName(true, tbl)))) } return sb }