Copy search when init do

This commit is contained in:
Jinzhu 2013-11-16 13:19:29 +08:00
parent cb53b5ed85
commit c3d2746912
4 changed files with 46 additions and 58 deletions

92
do.go
View File

@ -14,6 +14,7 @@ import (
type Do struct { type Do struct {
db *DB db *DB
search *search
model *Model model *Model
tableName string tableName string
value interface{} value interface{}
@ -27,10 +28,10 @@ type Do struct {
func (s *Do) table() string { func (s *Do) table() string {
if len(s.tableName) == 0 { if len(s.tableName) == 0 {
if len(s.db.search.tableName) == 0 { if len(s.search.tableName) == 0 {
s.tableName = s.model.tableName() s.tableName = s.model.tableName()
} else { } else {
s.tableName = s.db.search.tableName s.tableName = s.search.tableName
} }
} }
return s.tableName return s.tableName
@ -46,6 +47,11 @@ func (s *Do) err(err error) error {
func (s *Do) setModel(value interface{}) *Do { func (s *Do) setModel(value interface{}) *Do {
s.model = &Model{data: value, do: s} s.model = &Model{data: value, do: s}
s.value = value s.value = value
if s.db.search == nil {
s.search = &search{}
} else {
s.search = s.db.search
}
return s return s
} }
@ -191,10 +197,12 @@ func (s *Do) create() (i interface{}) {
} }
func (s *Do) updateAttrs(values interface{}, ignore_protected_attrs ...bool) *Do { func (s *Do) updateAttrs(values interface{}, ignore_protected_attrs ...bool) *Do {
ignore_protected := len(ignore_protected_attrs) > 0 && ignore_protected_attrs[0]
switch value := values.(type) { switch value := values.(type) {
case map[string]interface{}: case map[string]interface{}:
if len(value) > 0 { if len(value) > 0 {
results, has_update := s.model.updatedColumnsAndValues(value) results, has_update := s.model.updatedColumnsAndValues(value, ignore_protected)
if len(results) > 0 { if len(results) > 0 {
s.update_attrs = results s.update_attrs = results
} else if has_update { } else if has_update {
@ -218,16 +226,9 @@ func (s *Do) updateAttrs(values interface{}, ignore_protected_attrs ...bool) *Do
return s return s
} }
func (s *Do) prepareUpdateAttrs() (results map[string]interface{}, update bool) { func (s *Do) prepareUpdateSql() {
if len(s.updateAttrs) > 0 {
results, update = s.model.updatedColumnsAndValues(s.updateAttrs)
}
return
}
func (s *Do) prepareUpdateSql(results map[string]interface{}) {
var sqls []string var sqls []string
for key, value := range results { for key, value := range s.update_attrs {
sqls = append(sqls, fmt.Sprintf("%v = %v", key, s.addToVars(value))) sqls = append(sqls, fmt.Sprintf("%v = %v", key, s.addToVars(value)))
} }
@ -245,19 +246,11 @@ func (s *Do) prepareUpdateSql(results map[string]interface{}) {
} }
func (s *Do) update() *Do { func (s *Do) update() *Do {
update_attrs := s.updateAttrs
if len(update_attrs) > 0 {
var need_update bool
if update_attrs, need_update = s.prepareUpdateAttrs(); !need_update {
return s
}
}
s.model.callMethod("BeforeUpdate") s.model.callMethod("BeforeUpdate")
s.model.callMethod("BeforeSave") s.model.callMethod("BeforeSave")
s.saveBeforeAssociations() s.saveBeforeAssociations()
s.prepareUpdateSql(update_attrs)
s.prepareUpdateSql()
if !s.db.hasError() { if !s.db.hasError() {
s.exec() s.exec()
@ -274,7 +267,7 @@ func (s *Do) delete() *Do {
s.model.callMethod("BeforeDelete") s.model.callMethod("BeforeDelete")
if !s.db.hasError() { if !s.db.hasError() {
if !s.unscoped && s.model.hasColumn("DeletedAt") { if !s.search.unscope && s.model.hasColumn("DeletedAt") {
s.sql = fmt.Sprintf("UPDATE %v SET deleted_at=%v %v", s.table(), s.addToVars(time.Now()), s.combinedSql()) s.sql = fmt.Sprintf("UPDATE %v SET deleted_at=%v %v", s.table(), s.addToVars(time.Now()), s.combinedSql())
} else { } else {
s.sql = fmt.Sprintf("DELETE FROM %v %v", s.table(), s.combinedSql()) s.sql = fmt.Sprintf("DELETE FROM %v %v", s.table(), s.combinedSql())
@ -291,14 +284,12 @@ func (s *Do) prepareQuerySql() {
} }
func (s *Do) first() { func (s *Do) first() {
s.limitStr = "1" s.search.order(s.model.primaryKeyDb()).limit(1)
s.orderStrs = append(s.orderStrs, s.model.primaryKeyDb())
s.query() s.query()
} }
func (s *Do) last() { func (s *Do) last() {
s.limitStr = "1" s.search.order(s.model.primaryKeyDb() + " DESC").limit(1)
s.orderStrs = append(s.orderStrs, s.model.primaryKeyDb()+" DESC")
s.query() s.query()
} }
@ -355,7 +346,7 @@ func (s *Do) query() {
is_slice = true is_slice = true
dest_type = dest_out.Type().Elem() dest_type = dest_out.Type().Elem()
} else { } else {
s.limitStr = "1" s.search.limit(1)
} }
s.prepareQuerySql() s.prepareQuerySql()
@ -411,7 +402,6 @@ func (s *Do) count(value interface{}) {
} }
func (s *Do) pluck(column string, value interface{}) { func (s *Do) pluck(column string, value interface{}) {
s.selectStr = column
dest_out := reflect.Indirect(reflect.ValueOf(value)) dest_out := reflect.Indirect(reflect.ValueOf(value))
if dest_out.Kind() != reflect.Slice { if dest_out.Kind() != reflect.Slice {
@ -437,13 +427,6 @@ func (s *Do) pluck(column string, value interface{}) {
} }
} }
func (s *Do) where(where ...interface{}) *Do {
if len(where) > 0 {
s.whereClause = append(s.whereClause, map[string]interface{}{"query": where[0], "args": where[1:len(where)]})
}
return s
}
func (s *Do) primaryCondiation(value interface{}) string { func (s *Do) primaryCondiation(value interface{}) string {
return fmt.Sprintf("(%v = %v)", s.model.primaryKeyDb(), value) return fmt.Sprintf("(%v = %v)", s.model.primaryKeyDb(), value)
} }
@ -561,7 +544,7 @@ func (s *Do) buildNotCondition(clause map[string]interface{}) (str string) {
func (s *Do) whereSql() (sql string) { func (s *Do) whereSql() (sql string) {
var primary_condiations, and_conditions, or_conditions []string var primary_condiations, and_conditions, or_conditions []string
if !s.unscoped && s.model.hasColumn("DeletedAt") { if !s.search.unscope && s.model.hasColumn("DeletedAt") {
primary_condiations = append(primary_condiations, "(deleted_at IS NULL OR deleted_at <= '0001-01-02')") primary_condiations = append(primary_condiations, "(deleted_at IS NULL OR deleted_at <= '0001-01-02')")
} }
@ -569,15 +552,15 @@ func (s *Do) whereSql() (sql string) {
primary_condiations = append(primary_condiations, s.primaryCondiation(s.addToVars(s.model.primaryKeyValue()))) primary_condiations = append(primary_condiations, s.primaryCondiation(s.addToVars(s.model.primaryKeyValue())))
} }
for _, clause := range s.whereClause { for _, clause := range s.search.whereClause {
and_conditions = append(and_conditions, s.buildWhereCondition(clause)) and_conditions = append(and_conditions, s.buildWhereCondition(clause))
} }
for _, clause := range s.orClause { for _, clause := range s.search.orClause {
or_conditions = append(or_conditions, s.buildWhereCondition(clause)) or_conditions = append(or_conditions, s.buildWhereCondition(clause))
} }
for _, clause := range s.notClause { for _, clause := range s.search.notClause {
and_conditions = append(and_conditions, s.buildNotCondition(clause)) and_conditions = append(and_conditions, s.buildNotCondition(clause))
} }
@ -603,34 +586,34 @@ func (s *Do) whereSql() (sql string) {
} }
func (s *Do) selectSql() string { func (s *Do) selectSql() string {
if len(s.selectStr) == 0 { if len(s.search.selectStr) == 0 {
return "*" return "*"
} else { } else {
return s.selectStr return s.search.selectStr
} }
} }
func (s *Do) orderSql() string { func (s *Do) orderSql() string {
if len(s.orderStrs) == 0 { if len(s.search.orders) == 0 {
return "" return ""
} else { } else {
return " ORDER BY " + strings.Join(s.orderStrs, ",") return " ORDER BY " + strings.Join(s.search.orders, ",")
} }
} }
func (s *Do) limitSql() string { func (s *Do) limitSql() string {
if len(s.limitStr) == 0 { if len(s.search.limitStr) == 0 {
return "" return ""
} else { } else {
return " LIMIT " + s.limitStr return " LIMIT " + s.search.limitStr
} }
} }
func (s *Do) offsetSql() string { func (s *Do) offsetSql() string {
if len(s.offsetStr) == 0 { if len(s.search.offsetStr) == 0 {
return "" return ""
} else { } else {
return " OFFSET " + s.offsetStr return " OFFSET " + s.search.offsetStr
} }
} }
@ -733,16 +716,19 @@ func (s *Do) commit_or_rollback() {
} }
} }
func (s *Do) where(where ...interface{}) *Do {
if len(where) > 0 {
s.search.where(where[0], where[1:])
}
return s
}
func (s *Do) initialize() { func (s *Do) initialize() {
// TODO initializeWithSearchCondition // TODO initializeWithSearchCondition
} }
func (s *Do) updateAttrs_() {
// TODO return false if no updates
}
func (s *Do) initializeWithSearchCondition() { func (s *Do) initializeWithSearchCondition() {
for _, clause := range s.whereClause { for _, clause := range s.search.whereClause {
switch value := clause["query"].(type) { switch value := clause["query"].(type) {
case map[string]interface{}: case map[string]interface{}:
for k, v := range value { for k, v := range value {

View File

@ -82,17 +82,17 @@ func (s *DB) Unscoped() *DB {
} }
func (s *DB) First(out interface{}, where ...interface{}) *DB { func (s *DB) First(out interface{}, where ...interface{}) *DB {
s.clone().search.limit(1).where(where[0], where[1:]).db.do(out).first() s.clone().do(out).where(where...).first()
return s return s
} }
func (s *DB) Last(out interface{}, where ...interface{}) *DB { func (s *DB) Last(out interface{}, where ...interface{}) *DB {
s.clone().search.limit(1).where(where[0], where[1:]).db.do(out).last() s.clone().do(out).where(where...).last()
return s return s
} }
func (s *DB) Find(out interface{}, where ...interface{}) *DB { func (s *DB) Find(out interface{}, where ...interface{}) *DB {
s.clone().search.where(where[0], where[1:]).db.do(out).query() s.clone().do(out).where(where...).query()
return s return s
} }

View File

@ -100,7 +100,7 @@ func (m *Model) columnsHasValue(operation string) (fields []*Field) {
return return
} }
func (m *Model) updatedColumnsAndValues(values map[string]interface{}) (results map[string]interface{}, any_updated bool) { func (m *Model) updatedColumnsAndValues(values map[string]interface{}, ignore_protected_attrs bool) (results map[string]interface{}, any_updated bool) {
if m.data == nil { if m.data == nil {
return values, true return values, true
} }

View File

@ -13,7 +13,9 @@ func (s *DB) clone() *DB {
func (s *DB) do(data interface{}) *Do { func (s *DB) do(data interface{}) *Do {
s.data = data s.data = data
return &Do{db: s}.setModel(data) do := Do{db: s}
do.setModel(data)
return &do
} }
func (s *DB) err(err error) error { func (s *DB) err(err error) error {