123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- // Copyright GoFrame Author(https://github.com/gogf/gf). All Rights Reserved.
- //
- // 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 (
- "fmt"
- "github.com/gogf/gf/container/garray"
- "github.com/gogf/gf/text/gregex"
- "github.com/gogf/gf/text/gstr"
- "github.com/gogf/gf/util/gconv"
- "github.com/gogf/gf/util/gutil"
- )
- 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{"deleted_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.
- func (m *Model) Unscoped() *Model {
- model := m.getModel()
- model.unscoped = true
- return 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) getSoftFieldNameCreated(table ...string) string {
- // It checks whether this feature disabled.
- if m.db.GetConfig().TimeMaintainDisabled {
- return ""
- }
- tableName := ""
- if len(table) > 0 {
- tableName = table[0]
- } else {
- tableName = m.getPrimaryTableName()
- }
- config := m.db.GetConfig()
- if config.CreatedAt != "" {
- return m.getSoftFieldName(tableName, []string{config.CreatedAt})
- }
- 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) getSoftFieldNameUpdated(table ...string) (field string) {
- // It checks whether this feature disabled.
- if m.db.GetConfig().TimeMaintainDisabled {
- return ""
- }
- tableName := ""
- if len(table) > 0 {
- tableName = table[0]
- } else {
- tableName = m.getPrimaryTableName()
- }
- config := m.db.GetConfig()
- if config.UpdatedAt != "" {
- return m.getSoftFieldName(tableName, []string{config.UpdatedAt})
- }
- 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) getSoftFieldNameDeleted(table ...string) (field string) {
- // It checks whether this feature disabled.
- if m.db.GetConfig().TimeMaintainDisabled {
- return ""
- }
- tableName := ""
- if len(table) > 0 {
- tableName = table[0]
- } else {
- tableName = m.getPrimaryTableName()
- }
- config := m.db.GetConfig()
- if config.UpdatedAt != "" {
- return m.getSoftFieldName(tableName, []string{config.DeletedAt})
- }
- return m.getSoftFieldName(tableName, deletedFiledNames)
- }
- // getSoftFieldName retrieves and returns the field name of the table for possible key.
- func (m *Model) getSoftFieldName(table string, keys []string) (field string) {
- fieldsMap, _ := m.db.TableFields(table)
- if len(fieldsMap) > 0 {
- for _, key := range keys {
- field, _ = gutil.MapPossibleItemByKey(
- gconv.Map(fieldsMap), key,
- )
- if field != "" {
- return
- }
- }
- }
- return
- }
- // getConditionForSoftDeleting retrieves and returns the condition string for soft deleting.
- // It supports multiple tables string like:
- // "user u, user_detail ud"
- // "user u LEFT JOIN user_detail ud ON(ud.uid=u.uid)"
- // "user LEFT JOIN user_detail ON(user_detail.uid=user.uid)"
- // "user u LEFT JOIN user_detail ud ON(ud.uid=u.uid) LEFT JOIN user_stats us ON(us.uid=u.uid)"
- func (m *Model) getConditionForSoftDeleting() string {
- if m.unscoped {
- return ""
- }
- conditionArray := garray.NewStrArray()
- if gstr.Contains(m.tables, " JOIN ") {
- // Base table.
- match, _ := gregex.MatchString(`(.+?) [A-Z]+ JOIN`, m.tables)
- conditionArray.Append(m.getConditionOfTableStringForSoftDeleting(match[1]))
- // Multiple joined tables, exclude the sub query sql which contains char '(' and ')'.
- matches, _ := gregex.MatchAllString(`JOIN ([^()]+?) ON`, m.tables)
- for _, match := range matches {
- conditionArray.Append(m.getConditionOfTableStringForSoftDeleting(match[1]))
- }
- }
- if conditionArray.Len() == 0 && gstr.Contains(m.tables, ",") {
- // Multiple base tables.
- for _, s := range gstr.SplitAndTrim(m.tables, ",") {
- conditionArray.Append(m.getConditionOfTableStringForSoftDeleting(s))
- }
- }
- conditionArray.FilterEmpty()
- if conditionArray.Len() > 0 {
- return conditionArray.Join(" AND ")
- }
- // Only one table.
- if fieldName := m.getSoftFieldNameDeleted(); fieldName != "" {
- return fmt.Sprintf(`%s IS NULL`, m.db.QuoteWord(fieldName))
- }
- return ""
- }
- // getConditionOfTableStringForSoftDeleting does something as its name describes.
- func (m *Model) getConditionOfTableStringForSoftDeleting(s string) string {
- var (
- field = ""
- table = ""
- array1 = gstr.SplitAndTrim(s, " ")
- array2 = gstr.SplitAndTrim(array1[0], ".")
- )
- if len(array2) >= 2 {
- table = array2[1]
- } else {
- table = array2[0]
- }
- field = m.getSoftFieldNameDeleted(table)
- if field == "" {
- return ""
- }
- if len(array1) >= 3 {
- return fmt.Sprintf(`%s.%s IS NULL`, m.db.QuoteWord(array1[2]), m.db.QuoteWord(field))
- }
- if len(array1) >= 2 {
- return fmt.Sprintf(`%s.%s IS NULL`, m.db.QuoteWord(array1[1]), m.db.QuoteWord(field))
- }
- return fmt.Sprintf(`%s.%s IS NULL`, m.db.QuoteWord(table), m.db.QuoteWord(field))
- }
- // getPrimaryTableName parses and returns the primary table name.
- func (m *Model) getPrimaryTableName() string {
- array1 := gstr.SplitAndTrim(m.tables, ",")
- array2 := gstr.SplitAndTrim(array1[0], " ")
- array3 := gstr.SplitAndTrim(array2[0], ".")
- if len(array3) >= 2 {
- return array3[1]
- }
- return array3[0]
- }
|