package gorm import ( "fmt" ) type search struct { db *DB whereConditions []map[string]interface{} orConditions []map[string]interface{} notConditions []map[string]interface{} havingConditions []map[string]interface{} joinConditions []map[string]interface{} initAttrs []interface{} assignAttrs []interface{} selects map[string]interface{} omits []string orders []interface{} preload []searchPreload offset interface{} limit interface{} group string tableName string raw bool Unscoped bool ignoreOrderQuery bool } type searchPreload struct { schema string conditions []interface{} } func (s *search) clone() *search { clone := search{ db: s.db, whereConditions: make([]map[string]interface{}, len(s.whereConditions)), orConditions: make([]map[string]interface{}, len(s.orConditions)), notConditions: make([]map[string]interface{}, len(s.notConditions)), havingConditions: make([]map[string]interface{}, len(s.havingConditions)), joinConditions: make([]map[string]interface{}, len(s.joinConditions)), initAttrs: make([]interface{}, len(s.initAttrs)), assignAttrs: make([]interface{}, len(s.assignAttrs)), selects: s.selects, omits: make([]string, len(s.omits)), orders: make([]interface{}, len(s.orders)), preload: make([]searchPreload, len(s.preload)), offset: s.offset, limit: s.limit, group: s.group, tableName: s.tableName, raw: s.raw, Unscoped: s.Unscoped, ignoreOrderQuery: s.ignoreOrderQuery, } for i, value := range s.whereConditions { clone.whereConditions[i] = value } for i, value := range s.orConditions { clone.orConditions[i] = value } for i, value := range s.notConditions { clone.notConditions[i] = value } for i, value := range s.havingConditions { clone.havingConditions[i] = value } for i, value := range s.joinConditions { clone.joinConditions[i] = value } for i, value := range s.initAttrs { clone.initAttrs[i] = value } for i, value := range s.assignAttrs { clone.assignAttrs[i] = value } for i, value := range s.omits { clone.omits[i] = value } for i, value := range s.orders { clone.orders[i] = value } for i, value := range s.preload { clone.preload[i] = value } return &clone } func (s *search) Where(query interface{}, values ...interface{}) *search { s.whereConditions = append(s.whereConditions, map[string]interface{}{"query": query, "args": values}) return s } func (s *search) Not(query interface{}, values ...interface{}) *search { s.notConditions = append(s.notConditions, map[string]interface{}{"query": query, "args": values}) return s } func (s *search) Or(query interface{}, values ...interface{}) *search { s.orConditions = append(s.orConditions, map[string]interface{}{"query": query, "args": values}) return s } func (s *search) Attrs(attrs ...interface{}) *search { s.initAttrs = append(s.initAttrs, toSearchableMap(attrs...)) return s } func (s *search) Assign(attrs ...interface{}) *search { s.assignAttrs = append(s.assignAttrs, toSearchableMap(attrs...)) return s } func (s *search) Order(value interface{}, reorder ...bool) *search { if len(reorder) > 0 && reorder[0] { s.orders = []interface{}{} } if value != nil && value != "" { s.orders = append(s.orders, value) } return s } func (s *search) Select(query interface{}, args ...interface{}) *search { s.selects = map[string]interface{}{"query": query, "args": args} return s } func (s *search) Omit(columns ...string) *search { s.omits = columns return s } func (s *search) Limit(limit interface{}) *search { s.limit = limit return s } func (s *search) Offset(offset interface{}) *search { s.offset = offset return s } func (s *search) Group(query string) *search { s.group = s.getInterfaceAsSQL(query) return s } func (s *search) Having(query interface{}, values ...interface{}) *search { if val, ok := query.(*SqlExpr); ok { s.havingConditions = append(s.havingConditions, map[string]interface{}{"query": val.expr, "args": val.args}) } else { s.havingConditions = append(s.havingConditions, map[string]interface{}{"query": query, "args": values}) } return s } func (s *search) Joins(query string, values ...interface{}) *search { s.joinConditions = append(s.joinConditions, map[string]interface{}{"query": query, "args": values}) return s } func (s *search) Preload(schema string, values ...interface{}) *search { var preloads []searchPreload for _, preload := range s.preload { if preload.schema != schema { preloads = append(preloads, preload) } } preloads = append(preloads, searchPreload{schema, values}) s.preload = preloads return s } func (s *search) Raw(b bool) *search { s.raw = b return s } func (s *search) unscoped() *search { s.Unscoped = true return s } func (s *search) Table(name string) *search { s.tableName = name return s } func (s *search) getInterfaceAsSQL(value interface{}) (str string) { switch value.(type) { case string, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64: str = fmt.Sprintf("%v", value) default: s.db.AddError(ErrInvalidSQL) } if str == "-1" { return "" } return }