github.com/gogf/gf/v2@v2.7.4/database/gdb/gdb_core_utility.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 8 package gdb 9 10 import ( 11 "context" 12 "fmt" 13 14 "github.com/gogf/gf/v2/errors/gcode" 15 "github.com/gogf/gf/v2/errors/gerror" 16 "github.com/gogf/gf/v2/text/gregex" 17 "github.com/gogf/gf/v2/text/gstr" 18 "github.com/gogf/gf/v2/util/gutil" 19 ) 20 21 // GetDB returns the underlying DB. 22 func (c *Core) GetDB() DB { 23 return c.db 24 } 25 26 // GetLink creates and returns the underlying database link object with transaction checks. 27 // The parameter `master` specifies whether using the master node if master-slave configured. 28 func (c *Core) GetLink(ctx context.Context, master bool, schema string) (Link, error) { 29 tx := TXFromCtx(ctx, c.db.GetGroup()) 30 if tx != nil { 31 return &txLink{tx.GetSqlTX()}, nil 32 } 33 if master { 34 link, err := c.db.GetCore().MasterLink(schema) 35 if err != nil { 36 return nil, err 37 } 38 return link, nil 39 } 40 link, err := c.db.GetCore().SlaveLink(schema) 41 if err != nil { 42 return nil, err 43 } 44 return link, nil 45 } 46 47 // MasterLink acts like function Master but with additional `schema` parameter specifying 48 // the schema for the connection. It is defined for internal usage. 49 // Also see Master. 50 func (c *Core) MasterLink(schema ...string) (Link, error) { 51 db, err := c.db.Master(schema...) 52 if err != nil { 53 return nil, err 54 } 55 return &dbLink{ 56 DB: db, 57 isOnMaster: true, 58 }, nil 59 } 60 61 // SlaveLink acts like function Slave but with additional `schema` parameter specifying 62 // the schema for the connection. It is defined for internal usage. 63 // Also see Slave. 64 func (c *Core) SlaveLink(schema ...string) (Link, error) { 65 db, err := c.db.Slave(schema...) 66 if err != nil { 67 return nil, err 68 } 69 return &dbLink{ 70 DB: db, 71 isOnMaster: false, 72 }, nil 73 } 74 75 // QuoteWord checks given string `s` a word, 76 // if true it quotes `s` with security chars of the database 77 // and returns the quoted string; or else it returns `s` without any change. 78 // 79 // The meaning of a `word` can be considered as a column name. 80 func (c *Core) QuoteWord(s string) string { 81 s = gstr.Trim(s) 82 if s == "" { 83 return s 84 } 85 charLeft, charRight := c.db.GetChars() 86 return doQuoteWord(s, charLeft, charRight) 87 } 88 89 // QuoteString quotes string with quote chars. Strings like: 90 // "user", "user u", "user,user_detail", "user u, user_detail ut", "u.id asc". 91 // 92 // The meaning of a `string` can be considered as part of a statement string including columns. 93 func (c *Core) QuoteString(s string) string { 94 if !gregex.IsMatchString(regularFieldNameWithCommaRegPattern, s) { 95 return s 96 } 97 charLeft, charRight := c.db.GetChars() 98 return doQuoteString(s, charLeft, charRight) 99 } 100 101 // QuotePrefixTableName adds prefix string and quotes chars for the table. 102 // It handles table string like: 103 // "user", "user u", 104 // "user,user_detail", 105 // "user u, user_detail ut", 106 // "user as u, user_detail as ut". 107 // 108 // Note that, this will automatically checks the table prefix whether already added, 109 // if true it does nothing to the table name, or else adds the prefix to the table name. 110 func (c *Core) QuotePrefixTableName(table string) string { 111 charLeft, charRight := c.db.GetChars() 112 return doQuoteTableName(table, c.db.GetPrefix(), charLeft, charRight) 113 } 114 115 // GetChars returns the security char for current database. 116 // It does nothing in default. 117 func (c *Core) GetChars() (charLeft string, charRight string) { 118 return "", "" 119 } 120 121 // Tables retrieves and returns the tables of current schema. 122 // It's mainly used in cli tool chain for automatically generating the models. 123 func (c *Core) Tables(ctx context.Context, schema ...string) (tables []string, err error) { 124 return 125 } 126 127 // TableFields retrieves and returns the fields' information of specified table of current 128 // schema. 129 // 130 // The parameter `link` is optional, if given nil it automatically retrieves a raw sql connection 131 // as its link to proceed necessary sql query. 132 // 133 // Note that it returns a map containing the field name and its corresponding fields. 134 // As a map is unsorted, the TableField struct has an "Index" field marks its sequence in 135 // the fields. 136 // 137 // It's using cache feature to enhance the performance, which is never expired util the 138 // process restarts. 139 func (c *Core) TableFields(ctx context.Context, table string, schema ...string) (fields map[string]*TableField, err error) { 140 return 141 } 142 143 // ClearTableFields removes certain cached table fields of current configuration group. 144 func (c *Core) ClearTableFields(ctx context.Context, table string, schema ...string) (err error) { 145 tableFieldsCacheKey := genTableFieldsCacheKey( 146 c.db.GetGroup(), 147 gutil.GetOrDefaultStr(c.db.GetSchema(), schema...), 148 table, 149 ) 150 _, err = c.innerMemCache.Remove(ctx, tableFieldsCacheKey) 151 return 152 } 153 154 // ClearTableFieldsAll removes all cached table fields of current configuration group. 155 func (c *Core) ClearTableFieldsAll(ctx context.Context) (err error) { 156 var ( 157 keys, _ = c.innerMemCache.KeyStrings(ctx) 158 cachePrefix = cachePrefixTableFields 159 removedKeys = make([]any, 0) 160 ) 161 for _, key := range keys { 162 if gstr.HasPrefix(key, cachePrefix) { 163 removedKeys = append(removedKeys, key) 164 } 165 } 166 167 if len(removedKeys) > 0 { 168 err = c.innerMemCache.Removes(ctx, removedKeys) 169 } 170 return 171 } 172 173 // ClearCache removes cached sql result of certain table. 174 func (c *Core) ClearCache(ctx context.Context, table string) (err error) { 175 var ( 176 keys, _ = c.db.GetCache().KeyStrings(ctx) 177 cachePrefix = fmt.Sprintf(`%s%s@`, cachePrefixSelectCache, table) 178 removedKeys = make([]any, 0) 179 ) 180 for _, key := range keys { 181 if gstr.HasPrefix(key, cachePrefix) { 182 removedKeys = append(removedKeys, key) 183 } 184 } 185 if len(removedKeys) > 0 { 186 err = c.db.GetCache().Removes(ctx, removedKeys) 187 } 188 return 189 } 190 191 // ClearCacheAll removes all cached sql result from cache 192 func (c *Core) ClearCacheAll(ctx context.Context) (err error) { 193 if err = c.db.GetCache().Clear(ctx); err != nil { 194 return err 195 } 196 if err = c.GetInnerMemCache().Clear(ctx); err != nil { 197 return err 198 } 199 return 200 } 201 202 // HasField determine whether the field exists in the table. 203 func (c *Core) HasField(ctx context.Context, table, field string, schema ...string) (bool, error) { 204 table = c.guessPrimaryTableName(table) 205 tableFields, err := c.db.TableFields(ctx, table, schema...) 206 if err != nil { 207 return false, err 208 } 209 if len(tableFields) == 0 { 210 return false, gerror.NewCodef( 211 gcode.CodeNotFound, 212 `empty table fields for table "%s"`, table, 213 ) 214 } 215 fieldsArray := make([]string, len(tableFields)) 216 for k, v := range tableFields { 217 fieldsArray[v.Index] = k 218 } 219 charLeft, charRight := c.db.GetChars() 220 field = gstr.Trim(field, charLeft+charRight) 221 for _, f := range fieldsArray { 222 if f == field { 223 return true, nil 224 } 225 } 226 return false, nil 227 } 228 229 // guessPrimaryTableName parses and returns the primary table name. 230 func (c *Core) guessPrimaryTableName(tableStr string) string { 231 if tableStr == "" { 232 return "" 233 } 234 var ( 235 guessedTableName string 236 array1 = gstr.SplitAndTrim(tableStr, ",") 237 array2 = gstr.SplitAndTrim(array1[0], " ") 238 array3 = gstr.SplitAndTrim(array2[0], ".") 239 ) 240 if len(array3) >= 2 { 241 guessedTableName = array3[1] 242 } else { 243 guessedTableName = array3[0] 244 } 245 charL, charR := c.db.GetChars() 246 if charL != "" || charR != "" { 247 guessedTableName = gstr.Trim(guessedTableName, charL+charR) 248 } 249 if !gregex.IsMatchString(regularFieldNameRegPattern, guessedTableName) { 250 return "" 251 } 252 return guessedTableName 253 }