add custom CreatedAt/UpdatedAt/DeletedAt filed name configuration for package gdb

This commit is contained in:
Jack
2020-10-20 21:01:39 +08:00
parent ffe9ecc141
commit 561a541fa1
8 changed files with 76 additions and 28 deletions

View File

@ -128,6 +128,7 @@ type DB interface {
GetDryRun() bool
SetLogger(logger *glog.Logger)
GetLogger() *glog.Logger
GetConfig() *ConfigNode
SetMaxIdleConnCount(n int)
SetMaxOpenConnCount(n int)
SetMaxConnLifetime(d time.Duration)
@ -171,6 +172,7 @@ type Core struct {
dryrun *gtype.Bool // Dry run.
prefix string // Table prefix.
logger *glog.Logger // Logger.
config *ConfigNode // Current config node.
maxIdleConnCount int // Max idle connection count.
maxOpenConnCount int // Max open connection count.
maxConnLifetime time.Duration // Max TTL for a connection.
@ -304,6 +306,7 @@ func New(group ...string) (db DB, err error) {
dryrun: gtype.NewBool(),
logger: glog.New(),
prefix: node.Prefix,
config: node,
maxIdleConnCount: gDEFAULT_CONN_MAX_IDLE_COUNT,
maxConnLifetime: gDEFAULT_CONN_MAX_LIFE_TIME, // Default max connection life time if user does not configure.
}

View File

@ -11,6 +11,7 @@ import (
"database/sql"
"errors"
"fmt"
"github.com/gogf/gf/text/gstr"
"reflect"
"strings"
@ -455,7 +456,7 @@ func (c *Core) DoInsert(link Link, table string, data interface{}, option int, b
for k, _ := range dataMap {
// If it's SAVE operation,
// do not automatically update the creating time.
if utils.EqualFoldWithoutChars(k, gSOFT_FIELD_NAME_CREATE) {
if c.isSoftCreatedFiledName(k) {
continue
}
if len(updateStr) > 0 {
@ -602,7 +603,7 @@ func (c *Core) DoBatchInsert(link Link, table string, list interface{}, option i
for _, k := range keys {
// If it's SAVE operation,
// do not automatically update the creating time.
if utils.EqualFoldWithoutChars(k, gSOFT_FIELD_NAME_CREATE) {
if c.isSoftCreatedFiledName(k) {
continue
}
if len(updateStr) > 0 {
@ -829,3 +830,22 @@ func (c *Core) HasTable(name string) (bool, error) {
}
return false, nil
}
// isSoftCreatedFiledName checks and returns whether given filed name is an automatic-filled created time.
func (c *Core) isSoftCreatedFiledName(fieldName string) bool {
if fieldName == "" {
return false
}
if config := c.DB.GetConfig(); config.CreatedAt != "" {
if utils.EqualFoldWithoutChars(fieldName, config.CreatedAt) {
return true
}
return gstr.InArray(append([]string{config.CreatedAt}, createdFiledNames...), fieldName)
}
for _, v := range createdFiledNames {
if utils.EqualFoldWithoutChars(fieldName, v) {
return true
}
}
return false
}

View File

@ -39,6 +39,9 @@ type ConfigNode struct {
DryRun bool // (Optional) Dry run, which does SELECT but no INSERT/UPDATE/DELETE statements.
Weight int // (Optional) Weight for load balance calculating, it's useless if there's just one node.
Charset string // (Optional, "utf8mb4" in default) Custom charset when operating on database.
CreatedAt string // (Optional) The filed name of table for automatic-filled created datetime.
UpdatedAt string // (Optional) The filed name of table for automatic-filled updated datetime.
DeletedAt string // (Optional) The filed name of table for automatic-filled updated datetime.
LinkInfo string `json:"link"` // (Optional) Custom link information, when it is used, configuration Host/Port/User/Pass/Name are ignored.
MaxIdleConnCount int `json:"maxidle"` // (Optional) Max idle connection configuration for underlying connection pool.
MaxOpenConnCount int `json:"maxopen"` // (Optional) Max open connection configuration for underlying connection pool.
@ -212,3 +215,8 @@ func (c *Core) SetSchema(schema string) {
func (c *Core) GetSchema() string {
return c.schema.Val()
}
// GetConfig returns the current used node configuration.
func (c *Core) GetConfig() *ConfigNode {
return c.config
}

View File

@ -25,7 +25,7 @@ func (m *Model) Delete(where ...interface{}) (result sql.Result, err error) {
}
}()
var (
fieldNameDelete = m.getSoftFieldNameDelete()
fieldNameDelete = m.getSoftFieldNameDeleted()
conditionWhere, conditionExtra, conditionArgs = m.formatCondition(false)
)
// Soft deleting.

View File

@ -149,9 +149,9 @@ func (m *Model) doInsertWithOption(option int, data ...interface{}) (result sql.
}
var (
nowString = gtime.Now().String()
fieldNameCreate = m.getSoftFieldNameCreate()
fieldNameUpdate = m.getSoftFieldNameUpdate()
fieldNameDelete = m.getSoftFieldNameDelete()
fieldNameCreate = m.getSoftFieldNameCreated()
fieldNameUpdate = m.getSoftFieldNameUpdated()
fieldNameDelete = m.getSoftFieldNameDeleted()
)
// Batch operation.
if list, ok := m.data.(List); ok {

View File

@ -15,10 +15,10 @@ import (
"github.com/gogf/gf/util/gutil"
)
const (
gSOFT_FIELD_NAME_CREATE = "create_at"
gSOFT_FIELD_NAME_UPDATE = "update_at"
gSOFT_FIELD_NAME_DELETE = "delete_at"
var (
createdFiledNames = []string{"created_at", "create_at"} // Default filed names of table for automatic-filled created datetime.
updatedFiledNames = []string{"updated_at", "update_at"} // Default filed names of table for automatic-filled updated datetime.
deletedFiledNames = []string{"updated_at", "delete_at"} // Default filed names of table for automatic-filled deleted datetime.
)
// Unscoped disables the auto-update time feature for insert, update and delete options.
@ -31,49 +31,66 @@ func (m *Model) Unscoped() *Model {
// getSoftFieldNameCreate checks and returns the field name for record creating time.
// If there's no field name for storing creating time, it returns an empty string.
// It checks the key with or without cases or chars '-'/'_'/'.'/' '.
func (m *Model) getSoftFieldNameCreate(table ...string) string {
func (m *Model) getSoftFieldNameCreated(table ...string) string {
tableName := ""
if len(table) > 0 {
tableName = table[0]
} else {
tableName = m.getPrimaryTableName()
}
return m.getSoftFieldName(tableName, gSOFT_FIELD_NAME_CREATE)
config := m.db.GetConfig()
if config.CreatedAt != "" {
return m.getSoftFieldName(tableName, append([]string{config.CreatedAt}, createdFiledNames...))
}
return m.getSoftFieldName(tableName, createdFiledNames)
}
// getSoftFieldNameUpdate checks and returns the field name for record updating time.
// If there's no field name for storing updating time, it returns an empty string.
// It checks the key with or without cases or chars '-'/'_'/'.'/' '.
func (m *Model) getSoftFieldNameUpdate(table ...string) (field string) {
func (m *Model) getSoftFieldNameUpdated(table ...string) (field string) {
tableName := ""
if len(table) > 0 {
tableName = table[0]
} else {
tableName = m.getPrimaryTableName()
}
return m.getSoftFieldName(tableName, gSOFT_FIELD_NAME_UPDATE)
config := m.db.GetConfig()
if config.UpdatedAt != "" {
return m.getSoftFieldName(tableName, append([]string{config.UpdatedAt}, updatedFiledNames...))
}
return m.getSoftFieldName(tableName, updatedFiledNames)
}
// getSoftFieldNameDelete checks and returns the field name for record deleting time.
// If there's no field name for storing deleting time, it returns an empty string.
// It checks the key with or without cases or chars '-'/'_'/'.'/' '.
func (m *Model) getSoftFieldNameDelete(table ...string) (field string) {
func (m *Model) getSoftFieldNameDeleted(table ...string) (field string) {
tableName := ""
if len(table) > 0 {
tableName = table[0]
} else {
tableName = m.getPrimaryTableName()
}
return m.getSoftFieldName(tableName, gSOFT_FIELD_NAME_DELETE)
config := m.db.GetConfig()
if config.UpdatedAt != "" {
return m.getSoftFieldName(tableName, append([]string{config.DeletedAt}, deletedFiledNames...))
}
return m.getSoftFieldName(tableName, deletedFiledNames)
}
// getSoftFieldName retrieves and returns the field name of the table for possible key.
func (m *Model) getSoftFieldName(table string, key string) (field string) {
func (m *Model) getSoftFieldName(table string, keys []string) (field string) {
fieldsMap, _ := m.db.TableFields(table)
if len(fieldsMap) > 0 {
field, _ = gutil.MapPossibleItemByKey(
gconv.Map(fieldsMap), key,
)
for _, key := range keys {
field, _ = gutil.MapPossibleItemByKey(
gconv.Map(fieldsMap), key,
)
if field != "" {
return
}
}
}
return
}
@ -110,7 +127,7 @@ func (m *Model) getConditionForSoftDeleting() string {
return conditionArray.Join(" AND ")
}
// Only one table.
if fieldName := m.getSoftFieldNameDelete(); fieldName != "" {
if fieldName := m.getSoftFieldNameDeleted(); fieldName != "" {
return fmt.Sprintf(`%s IS NULL`, m.db.QuoteWord(fieldName))
}
return ""
@ -129,7 +146,7 @@ func (m *Model) getConditionOfTableStringForSoftDeleting(s string) string {
} else {
table = array2[0]
}
field = m.getSoftFieldNameDelete(table)
field = m.getSoftFieldNameDeleted(table)
if field == "" {
return ""
}

View File

@ -42,9 +42,9 @@ func (m *Model) Update(dataAndWhere ...interface{}) (result sql.Result, err erro
}
var (
updateData = m.data
fieldNameCreate = m.getSoftFieldNameCreate()
fieldNameUpdate = m.getSoftFieldNameUpdate()
fieldNameDelete = m.getSoftFieldNameDelete()
fieldNameCreate = m.getSoftFieldNameCreated()
fieldNameUpdate = m.getSoftFieldNameUpdated()
fieldNameDelete = m.getSoftFieldNameDeleted()
conditionWhere, conditionExtra, conditionArgs = m.formatCondition(false)
)
// Automatically update the record updating time.

View File

@ -204,9 +204,9 @@ CREATE TABLE %s (
gtest.C(t, func(t *gtest.T) {
model := db.Table(table1)
gtest.Assert(model.getSoftFieldNameCreate(table2), "createat")
gtest.Assert(model.getSoftFieldNameUpdate(table2), "updateat")
gtest.Assert(model.getSoftFieldNameDelete(table2), "deleteat")
gtest.Assert(model.getSoftFieldNameCreated(table2), "createat")
gtest.Assert(model.getSoftFieldNameUpdated(table2), "updateat")
gtest.Assert(model.getSoftFieldNameDeleted(table2), "deleteat")
})
}