2021-01-17 21:46:25 +08:00
|
|
|
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
2020-03-13 17:21:30 +08:00
|
|
|
//
|
|
|
|
// This Source Code Form is subject to the terms of the MIT License.
|
|
|
|
// If a copy of the MIT was not distributed with this file,
|
|
|
|
// You can obtain one at https://github.com/gogf/gf.
|
|
|
|
|
|
|
|
package gdb
|
|
|
|
|
|
|
|
import (
|
|
|
|
"database/sql"
|
2021-10-11 21:41:56 +08:00
|
|
|
"github.com/gogf/gf/v2/container/gset"
|
|
|
|
"github.com/gogf/gf/v2/errors/gcode"
|
2021-10-28 23:18:23 +08:00
|
|
|
"github.com/gogf/gf/v2/internal/utils"
|
2021-05-21 13:25:53 +08:00
|
|
|
"reflect"
|
|
|
|
|
2021-10-11 21:41:56 +08:00
|
|
|
"github.com/gogf/gf/v2/errors/gerror"
|
|
|
|
"github.com/gogf/gf/v2/os/gtime"
|
|
|
|
"github.com/gogf/gf/v2/text/gstr"
|
|
|
|
"github.com/gogf/gf/v2/util/gconv"
|
|
|
|
"github.com/gogf/gf/v2/util/gutil"
|
2020-03-13 17:21:30 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
// Batch sets the batch operation number for the model.
|
|
|
|
func (m *Model) Batch(batch int) *Model {
|
|
|
|
model := m.getModel()
|
|
|
|
model.batch = batch
|
|
|
|
return model
|
|
|
|
}
|
|
|
|
|
|
|
|
// Data sets the operation data for the model.
|
2021-02-08 17:57:21 +08:00
|
|
|
// The parameter `data` can be type of string/map/gmap/slice/struct/*struct, etc.
|
2020-12-27 00:11:26 +08:00
|
|
|
// Note that, it uses shallow value copying for `data` if `data` is type of map/slice
|
|
|
|
// to avoid changing it inside function.
|
2020-03-13 17:21:30 +08:00
|
|
|
// Eg:
|
|
|
|
// Data("uid=10000")
|
|
|
|
// Data("uid", 10000)
|
|
|
|
// Data("uid=? AND name=?", 10000, "john")
|
|
|
|
// Data(g.Map{"uid": 10000, "name":"john"})
|
|
|
|
// Data(g.Slice{g.Map{"uid": 10000, "name":"john"}, g.Map{"uid": 20000, "name":"smith"})
|
|
|
|
func (m *Model) Data(data ...interface{}) *Model {
|
|
|
|
model := m.getModel()
|
|
|
|
if len(data) > 1 {
|
2020-12-27 00:11:26 +08:00
|
|
|
if s := gconv.String(data[0]); gstr.Contains(s, "?") {
|
2020-03-13 17:21:30 +08:00
|
|
|
model.data = s
|
|
|
|
model.extraArgs = data[1:]
|
|
|
|
} else {
|
|
|
|
m := make(map[string]interface{})
|
|
|
|
for i := 0; i < len(data); i += 2 {
|
|
|
|
m[gconv.String(data[i])] = data[i+1]
|
|
|
|
}
|
|
|
|
model.data = m
|
|
|
|
}
|
|
|
|
} else {
|
2021-11-02 09:55:37 +08:00
|
|
|
switch value := data[0].(type) {
|
2020-03-13 17:21:30 +08:00
|
|
|
case Result:
|
2021-11-02 09:55:37 +08:00
|
|
|
model.data = value.List()
|
2021-06-16 21:44:31 +08:00
|
|
|
|
2020-03-13 17:21:30 +08:00
|
|
|
case Record:
|
2021-11-02 09:55:37 +08:00
|
|
|
model.data = value.Map()
|
2021-06-16 21:44:31 +08:00
|
|
|
|
2020-03-13 17:21:30 +08:00
|
|
|
case List:
|
2021-11-02 09:55:37 +08:00
|
|
|
list := make(List, len(value))
|
|
|
|
for k, v := range value {
|
2020-12-27 00:11:26 +08:00
|
|
|
list[k] = gutil.MapCopy(v)
|
|
|
|
}
|
|
|
|
model.data = list
|
2021-06-16 21:44:31 +08:00
|
|
|
|
2020-03-13 17:21:30 +08:00
|
|
|
case Map:
|
2021-11-02 09:55:37 +08:00
|
|
|
model.data = gutil.MapCopy(value)
|
2021-06-16 21:44:31 +08:00
|
|
|
|
2020-03-13 17:21:30 +08:00
|
|
|
default:
|
2020-09-24 23:40:44 +08:00
|
|
|
var (
|
2021-11-02 09:55:37 +08:00
|
|
|
reflectInfo = utils.OriginValueAndKind(value)
|
2020-09-24 23:40:44 +08:00
|
|
|
)
|
2021-10-28 23:18:23 +08:00
|
|
|
switch reflectInfo.OriginKind {
|
2020-03-13 17:21:30 +08:00
|
|
|
case reflect.Slice, reflect.Array:
|
2021-10-28 23:18:23 +08:00
|
|
|
list := make(List, reflectInfo.OriginValue.Len())
|
|
|
|
for i := 0; i < reflectInfo.OriginValue.Len(); i++ {
|
|
|
|
list[i] = ConvertDataForTableRecord(reflectInfo.OriginValue.Index(i).Interface())
|
2020-03-13 17:21:30 +08:00
|
|
|
}
|
|
|
|
model.data = list
|
2021-08-30 22:26:02 +08:00
|
|
|
|
2020-03-24 20:58:11 +08:00
|
|
|
case reflect.Map:
|
2020-10-10 17:29:38 +08:00
|
|
|
model.data = ConvertDataForTableRecord(data[0])
|
2021-08-30 22:26:02 +08:00
|
|
|
|
2020-03-24 20:58:11 +08:00
|
|
|
case reflect.Struct:
|
2021-11-02 09:55:37 +08:00
|
|
|
// If the `data` parameter is defined like `xxxForDao`,
|
|
|
|
// it then adds `OmitNilData` option for this condition,
|
|
|
|
// which will filter all nil parameters in `data`.
|
|
|
|
if gstr.HasSuffix(reflect.TypeOf(value).String(), modelForDaoSuffix) {
|
|
|
|
model = model.OmitNilData()
|
|
|
|
}
|
2021-09-17 19:26:56 +08:00
|
|
|
if v, ok := data[0].(iInterfaces); ok {
|
2020-07-25 10:54:48 +08:00
|
|
|
var (
|
|
|
|
array = v.Interfaces()
|
|
|
|
list = make(List, len(array))
|
|
|
|
)
|
2020-03-24 20:58:11 +08:00
|
|
|
for i := 0; i < len(array); i++ {
|
2020-10-10 17:29:38 +08:00
|
|
|
list[i] = ConvertDataForTableRecord(array[i])
|
2020-03-24 20:58:11 +08:00
|
|
|
}
|
|
|
|
model.data = list
|
|
|
|
} else {
|
2020-10-10 17:29:38 +08:00
|
|
|
model.data = ConvertDataForTableRecord(data[0])
|
2020-03-24 20:58:11 +08:00
|
|
|
}
|
2021-08-30 22:26:02 +08:00
|
|
|
|
2020-03-13 17:21:30 +08:00
|
|
|
default:
|
|
|
|
model.data = data[0]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return model
|
|
|
|
}
|
|
|
|
|
2021-06-16 21:44:31 +08:00
|
|
|
// OnDuplicate sets the operations when columns conflicts occurs.
|
|
|
|
// In MySQL, this is used for "ON DUPLICATE KEY UPDATE" statement.
|
|
|
|
// The parameter `onDuplicate` can be type of string/Raw/*Raw/map/slice.
|
2021-06-16 21:51:44 +08:00
|
|
|
// Example:
|
|
|
|
// OnDuplicate("nickname, age")
|
|
|
|
// OnDuplicate("nickname", "age")
|
|
|
|
// OnDuplicate(g.Map{
|
|
|
|
// "nickname": gdb.Raw("CONCAT('name_', VALUES(`nickname`))"),
|
|
|
|
// })
|
|
|
|
// OnDuplicate(g.Map{
|
|
|
|
// "nickname": "passport",
|
|
|
|
// })
|
|
|
|
func (m *Model) OnDuplicate(onDuplicate ...interface{}) *Model {
|
2021-06-16 21:44:31 +08:00
|
|
|
model := m.getModel()
|
2021-06-16 21:51:44 +08:00
|
|
|
if len(onDuplicate) > 1 {
|
|
|
|
model.onDuplicate = onDuplicate
|
|
|
|
} else {
|
|
|
|
model.onDuplicate = onDuplicate[0]
|
|
|
|
}
|
2021-06-16 21:44:31 +08:00
|
|
|
return model
|
|
|
|
}
|
|
|
|
|
|
|
|
// OnDuplicateEx sets the excluding columns for operations when columns conflicts occurs.
|
|
|
|
// In MySQL, this is used for "ON DUPLICATE KEY UPDATE" statement.
|
2021-06-16 21:51:44 +08:00
|
|
|
// The parameter `onDuplicateEx` can be type of string/map/slice.
|
|
|
|
// Example:
|
|
|
|
// OnDuplicateEx("passport, password")
|
|
|
|
// OnDuplicateEx("passport", "password")
|
|
|
|
// OnDuplicateEx(g.Map{
|
|
|
|
// "passport": "",
|
|
|
|
// "password": "",
|
|
|
|
// })
|
|
|
|
func (m *Model) OnDuplicateEx(onDuplicateEx ...interface{}) *Model {
|
2021-06-16 21:44:31 +08:00
|
|
|
model := m.getModel()
|
2021-06-16 21:51:44 +08:00
|
|
|
if len(onDuplicateEx) > 1 {
|
|
|
|
model.onDuplicateEx = onDuplicateEx
|
|
|
|
} else {
|
|
|
|
model.onDuplicateEx = onDuplicateEx[0]
|
|
|
|
}
|
2021-06-16 21:44:31 +08:00
|
|
|
return model
|
|
|
|
}
|
|
|
|
|
2020-03-13 17:21:30 +08:00
|
|
|
// Insert does "INSERT INTO ..." statement for the model.
|
2021-02-08 17:57:21 +08:00
|
|
|
// The optional parameter `data` is the same as the parameter of Model.Data function,
|
2020-03-13 17:21:30 +08:00
|
|
|
// see Model.Data.
|
|
|
|
func (m *Model) Insert(data ...interface{}) (result sql.Result, err error) {
|
2020-04-08 21:26:14 +08:00
|
|
|
if len(data) > 0 {
|
|
|
|
return m.Data(data...).Insert()
|
|
|
|
}
|
2020-12-29 20:30:29 +08:00
|
|
|
return m.doInsertWithOption(insertOptionDefault)
|
2020-03-13 17:21:30 +08:00
|
|
|
}
|
|
|
|
|
2021-05-02 12:17:06 +08:00
|
|
|
// InsertAndGetId performs action Insert and returns the last insert id that automatically generated.
|
|
|
|
func (m *Model) InsertAndGetId(data ...interface{}) (lastInsertId int64, err error) {
|
|
|
|
if len(data) > 0 {
|
|
|
|
return m.Data(data...).InsertAndGetId()
|
|
|
|
}
|
|
|
|
result, err := m.doInsertWithOption(insertOptionDefault)
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
return result.LastInsertId()
|
|
|
|
}
|
|
|
|
|
2020-03-13 17:21:30 +08:00
|
|
|
// InsertIgnore does "INSERT IGNORE INTO ..." statement for the model.
|
2021-02-08 17:57:21 +08:00
|
|
|
// The optional parameter `data` is the same as the parameter of Model.Data function,
|
2020-03-13 17:21:30 +08:00
|
|
|
// see Model.Data.
|
|
|
|
func (m *Model) InsertIgnore(data ...interface{}) (result sql.Result, err error) {
|
|
|
|
if len(data) > 0 {
|
2020-12-10 14:40:58 +08:00
|
|
|
return m.Data(data...).InsertIgnore()
|
2020-03-13 17:21:30 +08:00
|
|
|
}
|
2020-12-29 20:30:29 +08:00
|
|
|
return m.doInsertWithOption(insertOptionIgnore)
|
2020-03-13 17:21:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Replace does "REPLACE INTO ..." statement for the model.
|
2021-02-08 17:57:21 +08:00
|
|
|
// The optional parameter `data` is the same as the parameter of Model.Data function,
|
2020-03-13 17:21:30 +08:00
|
|
|
// see Model.Data.
|
|
|
|
func (m *Model) Replace(data ...interface{}) (result sql.Result, err error) {
|
|
|
|
if len(data) > 0 {
|
|
|
|
return m.Data(data...).Replace()
|
|
|
|
}
|
2020-12-29 20:30:29 +08:00
|
|
|
return m.doInsertWithOption(insertOptionReplace)
|
2020-03-13 17:21:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Save does "INSERT INTO ... ON DUPLICATE KEY UPDATE..." statement for the model.
|
2021-02-08 17:57:21 +08:00
|
|
|
// The optional parameter `data` is the same as the parameter of Model.Data function,
|
2020-03-13 17:21:30 +08:00
|
|
|
// see Model.Data.
|
|
|
|
//
|
|
|
|
// It updates the record if there's primary or unique index in the saving data,
|
|
|
|
// or else it inserts a new record into the table.
|
|
|
|
func (m *Model) Save(data ...interface{}) (result sql.Result, err error) {
|
|
|
|
if len(data) > 0 {
|
|
|
|
return m.Data(data...).Save()
|
|
|
|
}
|
2020-12-29 20:30:29 +08:00
|
|
|
return m.doInsertWithOption(insertOptionSave)
|
2020-04-08 21:26:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// doInsertWithOption inserts data with option parameter.
|
2021-06-16 21:44:31 +08:00
|
|
|
func (m *Model) doInsertWithOption(insertOption int) (result sql.Result, err error) {
|
2020-03-13 17:21:30 +08:00
|
|
|
defer func() {
|
|
|
|
if err == nil {
|
|
|
|
m.checkAndRemoveCache()
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
if m.data == nil {
|
2021-08-24 21:18:59 +08:00
|
|
|
return nil, gerror.NewCode(gcode.CodeMissingParameter, "inserting into table with empty data")
|
2020-03-13 17:21:30 +08:00
|
|
|
}
|
2020-04-08 21:26:14 +08:00
|
|
|
var (
|
2021-06-08 20:32:34 +08:00
|
|
|
list List
|
2020-04-08 21:26:14 +08:00
|
|
|
nowString = gtime.Now().String()
|
2020-10-20 21:01:39 +08:00
|
|
|
fieldNameCreate = m.getSoftFieldNameCreated()
|
|
|
|
fieldNameUpdate = m.getSoftFieldNameUpdated()
|
2020-04-08 21:26:14 +08:00
|
|
|
)
|
2021-06-08 20:32:34 +08:00
|
|
|
newData, err := m.filterDataForInsertOrUpdate(m.data)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2021-06-16 21:44:31 +08:00
|
|
|
|
2021-06-08 20:32:34 +08:00
|
|
|
// It converts any data to List type for inserting.
|
2021-06-16 21:44:31 +08:00
|
|
|
switch value := newData.(type) {
|
|
|
|
case Result:
|
|
|
|
list = value.List()
|
|
|
|
|
|
|
|
case Record:
|
|
|
|
list = List{value.Map()}
|
2021-06-08 20:32:34 +08:00
|
|
|
|
|
|
|
case List:
|
2021-06-16 21:44:31 +08:00
|
|
|
list = value
|
|
|
|
for i, v := range list {
|
|
|
|
list[i] = ConvertDataForTableRecord(v)
|
|
|
|
}
|
|
|
|
|
|
|
|
case Map:
|
|
|
|
list = List{ConvertDataForTableRecord(value)}
|
2021-06-08 20:32:34 +08:00
|
|
|
|
|
|
|
default:
|
2021-06-16 21:44:31 +08:00
|
|
|
var (
|
2021-10-28 23:18:23 +08:00
|
|
|
reflectInfo = utils.OriginValueAndKind(newData)
|
2021-06-16 21:44:31 +08:00
|
|
|
)
|
2021-10-28 23:18:23 +08:00
|
|
|
switch reflectInfo.OriginKind {
|
2021-06-16 21:44:31 +08:00
|
|
|
// If it's slice type, it then converts it to List type.
|
|
|
|
case reflect.Slice, reflect.Array:
|
2021-10-28 23:18:23 +08:00
|
|
|
list = make(List, reflectInfo.OriginValue.Len())
|
|
|
|
for i := 0; i < reflectInfo.OriginValue.Len(); i++ {
|
|
|
|
list[i] = ConvertDataForTableRecord(reflectInfo.OriginValue.Index(i).Interface())
|
2021-06-16 21:44:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
case reflect.Map:
|
|
|
|
list = List{ConvertDataForTableRecord(value)}
|
|
|
|
|
|
|
|
case reflect.Struct:
|
2021-09-17 19:26:56 +08:00
|
|
|
if v, ok := value.(iInterfaces); ok {
|
2021-06-16 21:44:31 +08:00
|
|
|
var (
|
|
|
|
array = v.Interfaces()
|
|
|
|
)
|
|
|
|
list = make(List, len(array))
|
|
|
|
for i := 0; i < len(array); i++ {
|
|
|
|
list[i] = ConvertDataForTableRecord(array[i])
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
list = List{ConvertDataForTableRecord(value)}
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
2021-10-28 23:18:23 +08:00
|
|
|
return result, gerror.NewCodef(
|
|
|
|
gcode.CodeInvalidParameter,
|
|
|
|
"unsupported data list type: %v",
|
|
|
|
reflectInfo.InputValue.Type(),
|
|
|
|
)
|
2021-06-16 21:44:31 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(list) < 1 {
|
2021-08-24 21:18:59 +08:00
|
|
|
return result, gerror.NewCode(gcode.CodeMissingParameter, "data list cannot be empty")
|
2020-04-08 21:26:14 +08:00
|
|
|
}
|
2021-06-16 21:44:31 +08:00
|
|
|
|
2021-06-08 20:32:34 +08:00
|
|
|
// Automatic handling for creating/updating time.
|
|
|
|
if !m.unscoped && (fieldNameCreate != "" || fieldNameUpdate != "") {
|
|
|
|
for k, v := range list {
|
2020-04-15 12:56:41 +08:00
|
|
|
if fieldNameCreate != "" {
|
2021-06-08 20:32:34 +08:00
|
|
|
v[fieldNameCreate] = nowString
|
2020-04-08 21:26:14 +08:00
|
|
|
}
|
2020-04-15 12:56:41 +08:00
|
|
|
if fieldNameUpdate != "" {
|
2021-06-08 20:32:34 +08:00
|
|
|
v[fieldNameUpdate] = nowString
|
2020-04-08 21:26:14 +08:00
|
|
|
}
|
2021-06-08 20:32:34 +08:00
|
|
|
list[k] = v
|
2020-04-08 21:26:14 +08:00
|
|
|
}
|
2020-03-13 17:21:30 +08:00
|
|
|
}
|
2021-06-16 21:44:31 +08:00
|
|
|
// Format DoInsertOption, especially for "ON DUPLICATE KEY UPDATE" statement.
|
|
|
|
columnNames := make([]string, 0, len(list[0]))
|
|
|
|
for k, _ := range list[0] {
|
|
|
|
columnNames = append(columnNames, k)
|
|
|
|
}
|
|
|
|
doInsertOption, err := m.formatDoInsertOption(insertOption, columnNames)
|
|
|
|
if err != nil {
|
|
|
|
return result, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return m.db.DoInsert(m.GetCtx(), m.getLink(true), m.tables, list, doInsertOption)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *Model) formatDoInsertOption(insertOption int, columnNames []string) (option DoInsertOption, err error) {
|
|
|
|
option = DoInsertOption{
|
|
|
|
InsertOption: insertOption,
|
|
|
|
BatchCount: m.getBatch(),
|
|
|
|
}
|
|
|
|
if insertOption == insertOptionSave {
|
|
|
|
onDuplicateExKeys, err := m.formatOnDuplicateExKeys(m.onDuplicateEx)
|
|
|
|
if err != nil {
|
|
|
|
return option, err
|
|
|
|
}
|
|
|
|
var (
|
|
|
|
onDuplicateExKeySet = gset.NewStrSetFrom(onDuplicateExKeys)
|
|
|
|
)
|
|
|
|
if m.onDuplicate != nil {
|
|
|
|
switch m.onDuplicate.(type) {
|
|
|
|
case Raw, *Raw:
|
|
|
|
option.OnDuplicateStr = gconv.String(m.onDuplicate)
|
|
|
|
|
|
|
|
default:
|
|
|
|
var (
|
2021-10-28 23:18:23 +08:00
|
|
|
reflectInfo = utils.OriginValueAndKind(m.onDuplicate)
|
2021-06-16 21:44:31 +08:00
|
|
|
)
|
2021-10-28 23:18:23 +08:00
|
|
|
switch reflectInfo.OriginKind {
|
2021-06-16 21:44:31 +08:00
|
|
|
case reflect.String:
|
|
|
|
option.OnDuplicateMap = make(map[string]interface{})
|
2021-10-28 23:18:23 +08:00
|
|
|
for _, v := range gstr.SplitAndTrim(reflectInfo.OriginValue.String(), ",") {
|
2021-06-16 21:44:31 +08:00
|
|
|
if onDuplicateExKeySet.Contains(v) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
option.OnDuplicateMap[v] = v
|
|
|
|
}
|
|
|
|
|
|
|
|
case reflect.Map:
|
|
|
|
option.OnDuplicateMap = make(map[string]interface{})
|
|
|
|
for k, v := range gconv.Map(m.onDuplicate) {
|
|
|
|
if onDuplicateExKeySet.Contains(k) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
option.OnDuplicateMap[k] = v
|
|
|
|
}
|
|
|
|
|
|
|
|
case reflect.Slice, reflect.Array:
|
|
|
|
option.OnDuplicateMap = make(map[string]interface{})
|
|
|
|
for _, v := range gconv.Strings(m.onDuplicate) {
|
|
|
|
if onDuplicateExKeySet.Contains(v) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
option.OnDuplicateMap[v] = v
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
2021-07-20 23:02:02 +08:00
|
|
|
return option, gerror.NewCodef(
|
2021-08-24 21:18:59 +08:00
|
|
|
gcode.CodeInvalidParameter,
|
2021-07-20 23:02:02 +08:00
|
|
|
`unsupported OnDuplicate parameter type "%s"`,
|
|
|
|
reflect.TypeOf(m.onDuplicate),
|
|
|
|
)
|
2021-06-16 21:44:31 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if onDuplicateExKeySet.Size() > 0 {
|
|
|
|
option.OnDuplicateMap = make(map[string]interface{})
|
|
|
|
for _, v := range columnNames {
|
|
|
|
if onDuplicateExKeySet.Contains(v) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
option.OnDuplicateMap[v] = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *Model) formatOnDuplicateExKeys(onDuplicateEx interface{}) ([]string, error) {
|
|
|
|
if onDuplicateEx == nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
2021-10-28 23:18:23 +08:00
|
|
|
reflectInfo = utils.OriginValueAndKind(onDuplicateEx)
|
2021-06-16 21:44:31 +08:00
|
|
|
)
|
2021-10-28 23:18:23 +08:00
|
|
|
switch reflectInfo.OriginKind {
|
2021-06-16 21:44:31 +08:00
|
|
|
case reflect.String:
|
2021-10-28 23:18:23 +08:00
|
|
|
return gstr.SplitAndTrim(reflectInfo.OriginValue.String(), ","), nil
|
2021-06-16 21:44:31 +08:00
|
|
|
|
|
|
|
case reflect.Map:
|
|
|
|
return gutil.Keys(onDuplicateEx), nil
|
|
|
|
|
|
|
|
case reflect.Slice, reflect.Array:
|
|
|
|
return gconv.Strings(onDuplicateEx), nil
|
|
|
|
|
|
|
|
default:
|
2021-07-20 23:02:02 +08:00
|
|
|
return nil, gerror.NewCodef(
|
2021-08-24 21:18:59 +08:00
|
|
|
gcode.CodeInvalidParameter,
|
2021-07-20 23:02:02 +08:00
|
|
|
`unsupported OnDuplicateEx parameter type "%s"`,
|
|
|
|
reflect.TypeOf(onDuplicateEx),
|
|
|
|
)
|
2021-06-16 21:44:31 +08:00
|
|
|
}
|
2021-06-08 20:32:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (m *Model) getBatch() int {
|
|
|
|
batch := defaultBatchNumber
|
|
|
|
if m.batch > 0 {
|
|
|
|
batch = m.batch
|
|
|
|
}
|
|
|
|
return batch
|
2020-03-13 17:21:30 +08:00
|
|
|
}
|