github.com/gogf/gf@v1.16.9/database/gdb/gdb_model_time.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/gogf/gf. 6 7 package gdb 8 9 import ( 10 "fmt" 11 "github.com/gogf/gf/container/garray" 12 "github.com/gogf/gf/text/gregex" 13 "github.com/gogf/gf/text/gstr" 14 "github.com/gogf/gf/util/gconv" 15 "github.com/gogf/gf/util/gutil" 16 ) 17 18 var ( 19 createdFiledNames = []string{"created_at", "create_at"} // Default filed names of table for automatic-filled created datetime. 20 updatedFiledNames = []string{"updated_at", "update_at"} // Default filed names of table for automatic-filled updated datetime. 21 deletedFiledNames = []string{"deleted_at", "delete_at"} // Default filed names of table for automatic-filled deleted datetime. 22 ) 23 24 // Unscoped disables the auto-update time feature for insert, update and delete options. 25 func (m *Model) Unscoped() *Model { 26 model := m.getModel() 27 model.unscoped = true 28 return model 29 } 30 31 // getSoftFieldNameCreate checks and returns the field name for record creating time. 32 // If there's no field name for storing creating time, it returns an empty string. 33 // It checks the key with or without cases or chars '-'/'_'/'.'/' '. 34 func (m *Model) getSoftFieldNameCreated(table ...string) string { 35 // It checks whether this feature disabled. 36 if m.db.GetConfig().TimeMaintainDisabled { 37 return "" 38 } 39 tableName := "" 40 if len(table) > 0 { 41 tableName = table[0] 42 } else { 43 tableName = m.tablesInit 44 } 45 config := m.db.GetConfig() 46 if config.CreatedAt != "" { 47 return m.getSoftFieldName(tableName, []string{config.CreatedAt}) 48 } 49 return m.getSoftFieldName(tableName, createdFiledNames) 50 } 51 52 // getSoftFieldNameUpdate checks and returns the field name for record updating time. 53 // If there's no field name for storing updating time, it returns an empty string. 54 // It checks the key with or without cases or chars '-'/'_'/'.'/' '. 55 func (m *Model) getSoftFieldNameUpdated(table ...string) (field string) { 56 // It checks whether this feature disabled. 57 if m.db.GetConfig().TimeMaintainDisabled { 58 return "" 59 } 60 tableName := "" 61 if len(table) > 0 { 62 tableName = table[0] 63 } else { 64 tableName = m.tablesInit 65 } 66 config := m.db.GetConfig() 67 if config.UpdatedAt != "" { 68 return m.getSoftFieldName(tableName, []string{config.UpdatedAt}) 69 } 70 return m.getSoftFieldName(tableName, updatedFiledNames) 71 } 72 73 // getSoftFieldNameDelete checks and returns the field name for record deleting time. 74 // If there's no field name for storing deleting time, it returns an empty string. 75 // It checks the key with or without cases or chars '-'/'_'/'.'/' '. 76 func (m *Model) getSoftFieldNameDeleted(table ...string) (field string) { 77 // It checks whether this feature disabled. 78 if m.db.GetConfig().TimeMaintainDisabled { 79 return "" 80 } 81 tableName := "" 82 if len(table) > 0 { 83 tableName = table[0] 84 } else { 85 tableName = m.tablesInit 86 } 87 config := m.db.GetConfig() 88 if config.UpdatedAt != "" { 89 return m.getSoftFieldName(tableName, []string{config.DeletedAt}) 90 } 91 return m.getSoftFieldName(tableName, deletedFiledNames) 92 } 93 94 // getSoftFieldName retrieves and returns the field name of the table for possible key. 95 func (m *Model) getSoftFieldName(table string, keys []string) (field string) { 96 fieldsMap, _ := m.TableFields(table) 97 if len(fieldsMap) > 0 { 98 for _, key := range keys { 99 field, _ = gutil.MapPossibleItemByKey( 100 gconv.Map(fieldsMap), key, 101 ) 102 if field != "" { 103 return 104 } 105 } 106 } 107 return 108 } 109 110 // getConditionForSoftDeleting retrieves and returns the condition string for soft deleting. 111 // It supports multiple tables string like: 112 // "user u, user_detail ud" 113 // "user u LEFT JOIN user_detail ud ON(ud.uid=u.uid)" 114 // "user LEFT JOIN user_detail ON(user_detail.uid=user.uid)" 115 // "user u LEFT JOIN user_detail ud ON(ud.uid=u.uid) LEFT JOIN user_stats us ON(us.uid=u.uid)" 116 func (m *Model) getConditionForSoftDeleting() string { 117 if m.unscoped { 118 return "" 119 } 120 conditionArray := garray.NewStrArray() 121 if gstr.Contains(m.tables, " JOIN ") { 122 // Base table. 123 match, _ := gregex.MatchString(`(.+?) [A-Z]+ JOIN`, m.tables) 124 conditionArray.Append(m.getConditionOfTableStringForSoftDeleting(match[1])) 125 // Multiple joined tables, exclude the sub query sql which contains char '(' and ')'. 126 matches, _ := gregex.MatchAllString(`JOIN ([^()]+?) ON`, m.tables) 127 for _, match := range matches { 128 conditionArray.Append(m.getConditionOfTableStringForSoftDeleting(match[1])) 129 } 130 } 131 if conditionArray.Len() == 0 && gstr.Contains(m.tables, ",") { 132 // Multiple base tables. 133 for _, s := range gstr.SplitAndTrim(m.tables, ",") { 134 conditionArray.Append(m.getConditionOfTableStringForSoftDeleting(s)) 135 } 136 } 137 conditionArray.FilterEmpty() 138 if conditionArray.Len() > 0 { 139 return conditionArray.Join(" AND ") 140 } 141 // Only one table. 142 if fieldName := m.getSoftFieldNameDeleted(); fieldName != "" { 143 return fmt.Sprintf(`%s IS NULL`, m.db.GetCore().QuoteWord(fieldName)) 144 } 145 return "" 146 } 147 148 // getConditionOfTableStringForSoftDeleting does something as its name describes. 149 func (m *Model) getConditionOfTableStringForSoftDeleting(s string) string { 150 var ( 151 field = "" 152 table = "" 153 array1 = gstr.SplitAndTrim(s, " ") 154 array2 = gstr.SplitAndTrim(array1[0], ".") 155 ) 156 if len(array2) >= 2 { 157 table = array2[1] 158 } else { 159 table = array2[0] 160 } 161 field = m.getSoftFieldNameDeleted(table) 162 if field == "" { 163 return "" 164 } 165 if len(array1) >= 3 { 166 return fmt.Sprintf(`%s.%s IS NULL`, m.db.GetCore().QuoteWord(array1[2]), m.db.GetCore().QuoteWord(field)) 167 } 168 if len(array1) >= 2 { 169 return fmt.Sprintf(`%s.%s IS NULL`, m.db.GetCore().QuoteWord(array1[1]), m.db.GetCore().QuoteWord(field)) 170 } 171 return fmt.Sprintf(`%s.%s IS NULL`, m.db.GetCore().QuoteWord(table), m.db.GetCore().QuoteWord(field)) 172 }