This commit is contained in:
Lunny Xiao 2013-12-04 20:25:47 +08:00
commit f3b7c3c7dc
1 changed files with 95 additions and 53 deletions

View File

@ -24,9 +24,12 @@ type Session struct {
IsAutoClose bool
// !nashtsai! storing these beans due to yet committed tx
afterInsertBeans []interface{}
afterUpdateBeans []interface{}
afterDeleteBeans []interface{}
// afterInsertBeans []interface{}
// afterUpdateBeans []interface{}
// afterDeleteBeans []interface{}
afterInsertBeans map[interface{}]*[]func(interface{})
afterUpdateBeans map[interface{}]*[]func(interface{})
afterDeleteBeans map[interface{}]*[]func(interface{})
// --
beforeClosures []func(interface{})
@ -42,9 +45,9 @@ func (session *Session) Init() {
session.IsAutoClose = false
// !nashtsai! is lazy init better?
session.afterInsertBeans = make([]interface{}, 0)
session.afterUpdateBeans = make([]interface{}, 0)
session.afterDeleteBeans = make([]interface{}, 0)
session.afterInsertBeans = make(map[interface{}]*[]func(interface{}), 0)
session.afterUpdateBeans = make(map[interface{}]*[]func(interface{}), 0)
session.afterDeleteBeans = make(map[interface{}]*[]func(interface{}), 0)
session.beforeClosures = make([]func(interface{}), 0)
session.afterClosures = make([]func(interface{}), 0)
}
@ -286,53 +289,57 @@ func (session *Session) Commit() error {
var err error
if err = session.Tx.Commit(); err == nil {
// handle processors after tx committed
for _, elem := range session.afterInsertBeans {
for _, closure := range session.afterClosures {
closure(elem)
closureCallFunc := func(closuresPtr *[]func(interface{}), bean interface{}) {
if closuresPtr != nil {
for _, closure := range *closuresPtr {
closure(bean)
}
}
}
if processor, ok := interface{}(elem).(AfterInsertProcessor); ok {
for bean, closuresPtr := range session.afterInsertBeans {
closureCallFunc(closuresPtr, bean)
if processor, ok := interface{}(bean).(AfterInsertProcessor); ok {
processor.AfterInsert()
}
}
for _, elem := range session.afterUpdateBeans {
for _, closure := range session.afterClosures {
closure(elem)
}
if processor, ok := interface{}(elem).(AfterUpdateProcessor); ok {
for bean, closuresPtr := range session.afterUpdateBeans {
closureCallFunc(closuresPtr, bean)
if processor, ok := interface{}(bean).(AfterUpdateProcessor); ok {
processor.AfterUpdate()
}
}
for _, elem := range session.afterDeleteBeans {
for _, closure := range session.afterClosures {
closure(elem)
}
if processor, ok := interface{}(elem).(AfterDeleteProcessor); ok {
for bean, closuresPtr := range session.afterDeleteBeans {
closureCallFunc(closuresPtr, bean)
if processor, ok := interface{}(bean).(AfterDeleteProcessor); ok {
processor.AfterDelete()
}
}
cleanUpFunc := func(slices *[]interface{}) {
cleanUpFunc := func(slices *map[interface{}]*[]func(interface{})) {
if len(*slices) > 0 {
*slices = make([]interface{}, 0)
}
}
cleanUpProcessorsFunc := func(slices *[]func(interface{})) {
if len(*slices) > 0 {
*slices = make([]func(interface{}), 0)
*slices = make(map[interface{}]*[]func(interface{}), 0)
}
}
cleanUpFunc(&session.afterInsertBeans)
cleanUpFunc(&session.afterUpdateBeans)
cleanUpFunc(&session.afterDeleteBeans)
// !nash! should session based processors get cleanup?
cleanUpProcessorsFunc(&session.afterClosures)
}
return err
}
return nil
}
func cleanupProcessorsClosures(slices *[]func(interface{})) {
if len(*slices) > 0 {
*slices = make([]func(interface{}), 0)
}
}
func (session *Session) scanMapIntoStruct(obj interface{}, objMap map[string][]byte) error {
dataStruct := reflect.Indirect(reflect.ValueOf(obj))
if dataStruct.Kind() != reflect.Struct {
@ -1425,6 +1432,7 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error
colPlaces := make([]string, 0)
// handle BeforeInsertProcessor
// !nashtsai! does user expect it's same slice to passed closure when using Before()/After() when insert multi??
for _, closure := range session.beforeClosures {
closure(elemValue)
}
@ -1491,6 +1499,7 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error
}
colMultiPlaces = append(colMultiPlaces, strings.Join(colPlaces, ", "))
}
cleanupProcessorsClosures(&session.beforeClosures)
statement := fmt.Sprintf("INSERT INTO %v%v%v (%v%v%v) VALUES (%v)",
session.Engine.QuoteStr(),
@ -1510,11 +1519,12 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error
session.cacheInsert(session.Statement.TableName())
}
hasAfterClosures := len(session.afterClosures) > 0
lenAfterClosures := len(session.afterClosures)
for i := 0; i < size; i++ {
elemValue := sliceValue.Index(i).Interface()
// handle AfterInsertProcessor
if session.IsAutoCommit {
// !nashtsai! does user expect it's same slice to passed closure when using Before()/After() when insert multi??
for _, closure := range session.afterClosures {
closure(elemValue)
}
@ -1522,16 +1532,23 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error
processor.AfterInsert()
}
} else {
if hasAfterClosures {
session.afterInsertBeans = append(session.afterInsertBeans, elemValue)
if lenAfterClosures > 0 {
if value, has := session.afterInsertBeans[elemValue]; has && value != nil {
*value = append(*value, session.afterClosures...)
} else {
if _, ok := interface{}(elemValue).(AfterInsertProcessor); ok {
session.afterInsertBeans = append(session.afterInsertBeans, elemValue)
}
}
}
afterClosures := make([]func(interface{}), lenAfterClosures)
copy(afterClosures, session.afterClosures)
session.afterInsertBeans[elemValue] = &afterClosures
}
} else {
if _, ok := interface{}(elemValue).(AfterInsertProcessor); ok {
session.afterInsertBeans[elemValue] = nil
}
}
}
}
cleanupProcessorsClosures(&session.afterClosures)
return res.RowsAffected()
}
@ -1808,11 +1825,10 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
for _, closure := range session.beforeClosures {
closure(bean)
}
cleanupProcessorsClosures(&session.beforeClosures) // cleanup after used
if processor, ok := interface{}(bean).(BeforeInsertProcessor); ok {
session.Engine.LogDebug(session.Statement.TableName(), " has before insert processor")
processor.BeforeInsert()
} else {
session.Engine.LogDebug(session.Statement.TableName(), " has no before insert processor")
}
// --
@ -1840,18 +1856,26 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
closure(bean)
}
if processor, ok := interface{}(bean).(AfterInsertProcessor); ok {
session.Engine.LogDebug(session.Statement.TableName(), " has after insert processor")
processor.AfterInsert()
}
} else {
if len(session.afterClosures) > 0 {
session.afterInsertBeans = append(session.afterInsertBeans, bean)
lenAfterClosures := len(session.afterClosures)
if lenAfterClosures > 0 {
if value, has := session.afterInsertBeans[bean]; has && value != nil {
*value = append(*value, session.afterClosures...)
} else {
afterClosures := make([]func(interface{}), lenAfterClosures)
copy(afterClosures, session.afterClosures)
session.afterInsertBeans[bean] = &afterClosures
}
} else {
if _, ok := interface{}(bean).(AfterInsertProcessor); ok {
session.afterInsertBeans = append(session.afterInsertBeans, bean)
session.afterInsertBeans[bean] = nil
}
}
}
cleanupProcessorsClosures(&session.afterClosures) // cleanup after used
}
// for postgres, many of them didn't implement lastInsertId, so we should
@ -2142,7 +2166,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
for _, closure := range session.beforeClosures {
closure(bean)
}
cleanupProcessorsClosures(&session.beforeClosures) // cleanup after used
if processor, ok := interface{}(bean).(BeforeUpdateProcessor); ok {
processor.BeforeUpdate()
}
@ -2256,14 +2280,23 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
processor.AfterUpdate()
}
} else {
if len(session.afterClosures) > 0 {
session.afterUpdateBeans = append(session.afterUpdateBeans, bean)
lenAfterClosures := len(session.afterClosures)
if lenAfterClosures > 0 {
if value, has := session.afterUpdateBeans[bean]; has && value != nil {
*value = append(*value, session.afterClosures...)
} else {
if _, ok := interface{}(bean).(AfterUpdateProcessor); ok {
session.afterUpdateBeans = append(session.afterUpdateBeans, bean)
afterClosures := make([]func(interface{}), lenAfterClosures)
copy(afterClosures, session.afterClosures)
session.afterUpdateBeans[bean] = &afterClosures
}
} else {
if _, ok := interface{}(bean).(AfterInsertProcessor); ok {
session.afterUpdateBeans[bean] = nil
}
}
}
cleanupProcessorsClosures(&session.afterClosures) // cleanup after used
// --
return res.RowsAffected()
@ -2335,6 +2368,7 @@ func (session *Session) Delete(bean interface{}) (int64, error) {
for _, closure := range session.beforeClosures {
closure(bean)
}
cleanupProcessorsClosures(&session.beforeClosures)
if processor, ok := interface{}(bean).(BeforeDeleteProcessor); ok {
processor.BeforeDelete()
@ -2379,18 +2413,26 @@ func (session *Session) Delete(bean interface{}) (int64, error) {
closure(bean)
}
if processor, ok := interface{}(bean).(AfterDeleteProcessor); ok {
session.Engine.LogDebug(session.Statement.TableName(), " has after update processor")
processor.AfterDelete()
}
} else {
if len(session.afterClosures) > 0 {
session.afterDeleteBeans = append(session.afterDeleteBeans, bean)
lenAfterClosures := len(session.afterClosures)
if lenAfterClosures > 0 {
if value, has := session.afterDeleteBeans[bean]; has && value != nil {
*value = append(*value, session.afterClosures...)
} else {
if _, ok := interface{}(bean).(AfterDeleteProcessor); ok {
session.afterDeleteBeans = append(session.afterDeleteBeans, bean)
afterClosures := make([]func(interface{}), lenAfterClosures)
copy(afterClosures, session.afterClosures)
session.afterDeleteBeans[bean] = &afterClosures
}
} else {
if _, ok := interface{}(bean).(AfterInsertProcessor); ok {
session.afterDeleteBeans[bean] = nil
}
}
}
cleanupProcessorsClosures(&session.afterClosures)
// --
return res.RowsAffected()