fix: fix inseart id auto increment(#2167)

This commit is contained in:
luhengyu 2023-08-17 15:50:38 +08:00
parent 18f8e7a86c
commit 4a9fb23c4e
4 changed files with 130 additions and 32 deletions

View File

@ -47,6 +47,9 @@ type Engine struct {
DatabaseTZ *time.Location // The timezone of the database
logSessionID bool // create session id
autoIncrementIncrement int64 // auto increment increment default 1
lastInsertIDReversed bool // create id reversed
}
// NewEngine new a db manager according to the parameter. Currently support four
@ -71,16 +74,18 @@ func newEngine(driverName, dataSourceName string, dialect dialects.Dialect, db *
tagParser := tags.NewParser("xorm", dialect, mapper, mapper, cacherMgr)
engine := &Engine{
dialect: dialect,
driver: dialects.QueryDriver(driverName),
TZLocation: time.Local,
defaultContext: context.Background(),
cacherMgr: cacherMgr,
tagParser: tagParser,
driverName: driverName,
dataSourceName: dataSourceName,
db: db,
logSessionID: false,
dialect: dialect,
driver: dialects.QueryDriver(driverName),
TZLocation: time.Local,
defaultContext: context.Background(),
cacherMgr: cacherMgr,
tagParser: tagParser,
driverName: driverName,
dataSourceName: dataSourceName,
db: db,
logSessionID: false,
autoIncrementIncrement: 1,
lastInsertIDReversed: false,
}
if dialect.URI().DBType == schemas.SQLITE {
@ -144,6 +149,16 @@ func (engine *Engine) SetQuotePolicy(quotePolicy dialects.QuotePolicy) {
engine.dialect.SetQuotePolicy(quotePolicy)
}
// SetAutoIncrementIncrement set insert id auto increment increment
func (engine *Engine) SetAutoIncrementIncrement(increment int64) {
engine.autoIncrementIncrement = increment
}
// SetLastInsertIDReversed set insert id reversed
func (engine *Engine) SetLastInsertIDReversed(reversed bool) {
engine.lastInsertIDReversed = reversed
}
// BufferSize sets buffer size for iterate
func (engine *Engine) BufferSize(size int) *Session {
session := engine.NewSession()

View File

@ -206,6 +206,16 @@ func (eg *EngineGroup) SetQuotePolicy(quotePolicy dialects.QuotePolicy) {
}
}
// SetAutoIncrementIncrement set insert id auto increment increment
func (eg *EngineGroup) SetAutoIncrementIncrement(increment int64) {
eg.autoIncrementIncrement = increment
}
// SetLastInsertIDReversed set insert id reversed
func (eg *EngineGroup) SetLastInsertIDReversed(reversed bool) {
eg.lastInsertIDReversed = reversed
}
// SetTableMapper set the table name mapping rule
func (eg *EngineGroup) SetTableMapper(mapper names.Mapper) {
eg.Engine.SetTableMapper(mapper)

View File

@ -117,6 +117,8 @@ type EngineInterface interface {
SetTableMapper(names.Mapper)
SetTZDatabase(tz *time.Location)
SetTZLocation(tz *time.Location)
SetAutoIncrementIncrement(increment int64)
SetLastInsertIDReversed(reversed bool)
AddHook(hook contexts.Hook)
ShowSQL(show ...bool)
Sync(...interface{}) error

View File

@ -210,33 +210,104 @@ func (session *Session) insertMultipleStruct(rowsSlicePtr interface{}) (int64, e
_ = session.cacheInsert(tableName)
lenAfterClosures := len(session.afterClosures)
for i := 0; i < size; i++ {
elemValue := reflect.Indirect(sliceValue.Index(i)).Addr().Interface()
var id int64
if table.AutoIncrement != "" {
id, err = res.LastInsertId()
if err != nil || id <= 0 {
return res.RowsAffected()
}
}
// 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)
}
if processor, ok := elemValue.(AfterInsertProcessor); ok {
processor.AfterInsert()
}
} else {
if lenAfterClosures > 0 {
if value, has := session.afterInsertBeans[elemValue]; has && value != nil {
*value = append(*value, session.afterClosures...)
} else {
afterClosures := make([]func(interface{}), lenAfterClosures)
copy(afterClosures, session.afterClosures)
session.afterInsertBeans[elemValue] = &afterClosures
lenAfterClosures := len(session.afterClosures)
if session.engine.lastInsertIDReversed {
for i := size - 1; i >= 0; i-- {
elemValue := reflect.Indirect(sliceValue.Index(i)).Addr().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)
}
if processor, ok := elemValue.(AfterInsertProcessor); ok {
processor.AfterInsert()
}
} else {
if _, ok := elemValue.(AfterInsertProcessor); ok {
session.afterInsertBeans[elemValue] = nil
if lenAfterClosures > 0 {
if value, has := session.afterInsertBeans[elemValue]; has && value != nil {
*value = append(*value, session.afterClosures...)
} else {
afterClosures := make([]func(interface{}), lenAfterClosures)
copy(afterClosures, session.afterClosures)
session.afterInsertBeans[elemValue] = &afterClosures
}
} else {
if _, ok := elemValue.(AfterInsertProcessor); ok {
session.afterInsertBeans[elemValue] = nil
}
}
}
// handle auto increment
aiValue, err := table.AutoIncrColumn().ValueOf(elemValue)
if err != nil {
session.engine.logger.Errorf("%v", err)
}
if aiValue == nil || !aiValue.IsValid() || !aiValue.CanSet() {
continue
}
if err := convert.AssignValue(*aiValue, id); err != nil {
return 0, err
}
id -= session.engine.autoIncrementIncrement
}
} else {
for i := 0; i < size; i++ {
elemValue := reflect.Indirect(sliceValue.Index(i)).Addr().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)
}
if processor, ok := elemValue.(AfterInsertProcessor); ok {
processor.AfterInsert()
}
} else {
if lenAfterClosures > 0 {
if value, has := session.afterInsertBeans[elemValue]; has && value != nil {
*value = append(*value, session.afterClosures...)
} else {
afterClosures := make([]func(interface{}), lenAfterClosures)
copy(afterClosures, session.afterClosures)
session.afterInsertBeans[elemValue] = &afterClosures
}
} else {
if _, ok := elemValue.(AfterInsertProcessor); ok {
session.afterInsertBeans[elemValue] = nil
}
}
}
// handle auto increment
aiValue, err := table.AutoIncrColumn().ValueOf(elemValue)
if err != nil {
session.engine.logger.Errorf("%v", err)
}
if aiValue == nil || !aiValue.IsValid() || !aiValue.CanSet() {
continue
}
if err := convert.AssignValue(*aiValue, id); err != nil {
return 0, err
}
id += session.engine.autoIncrementIncrement
}
}