github.com/zhongdalu/gf@v1.0.0/g/database/gdb/gdb_structure.go (about)

     1  // Copyright 2019 gf Author(https://github.com/zhongdalu/gf). 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/zhongdalu/gf.
     6  
     7  package gdb
     8  
     9  import (
    10  	"fmt"
    11  	"strings"
    12  
    13  	"github.com/zhongdalu/gf/g/encoding/gbinary"
    14  
    15  	"github.com/zhongdalu/gf/g/text/gregex"
    16  	"github.com/zhongdalu/gf/g/util/gconv"
    17  )
    18  
    19  //// 同步数据库表结构到内存中
    20  //func (bs *dbBase) syncTableStructure() {
    21  //    bs.tables = make(map[string]map[string]string)
    22  //    for _, table := range bs.db.getTables() {
    23  //        bs.tables[table], _ = bs.db.getTableFields(table)
    24  //    }
    25  //}
    26  
    27  // 字段类型转换,将数据库字段类型转换为golang变量类型
    28  func (bs *dbBase) convertValue(fieldValue []byte, fieldType string) interface{} {
    29  	t, _ := gregex.ReplaceString(`\(.+\)`, "", fieldType)
    30  	t = strings.ToLower(t)
    31  	switch t {
    32  	case "binary", "varbinary", "blob", "tinyblob", "mediumblob", "longblob":
    33  		return fieldValue
    34  
    35  	case "int", "tinyint", "small_int", "medium_int":
    36  		return gconv.Int(string(fieldValue))
    37  
    38  	case "big_int":
    39  		return gconv.Int64(string(fieldValue))
    40  
    41  	case "float", "double", "decimal":
    42  		return gconv.Float64(string(fieldValue))
    43  
    44  	case "bit":
    45  		s := string(fieldValue)
    46  		// 这里的字符串判断是为兼容不同的数据库类型,如: mssql
    47  		if strings.EqualFold(s, "true") {
    48  			return 1
    49  		}
    50  		if strings.EqualFold(s, "false") {
    51  			return 0
    52  		}
    53  		return gbinary.BeDecodeToInt64(fieldValue)
    54  
    55  	case "bool":
    56  		return gconv.Bool(fieldValue)
    57  
    58  	default:
    59  		// 自动识别类型, 以便默认支持更多数据库类型
    60  		switch {
    61  		case strings.Contains(t, "int"):
    62  			return gconv.Int(string(fieldValue))
    63  
    64  		case strings.Contains(t, "text") || strings.Contains(t, "char"):
    65  			return string(fieldValue)
    66  
    67  		case strings.Contains(t, "float") || strings.Contains(t, "double"):
    68  			return gconv.Float64(string(fieldValue))
    69  
    70  		case strings.Contains(t, "bool"):
    71  			return gconv.Bool(string(fieldValue))
    72  
    73  		case strings.Contains(t, "binary") || strings.Contains(t, "blob"):
    74  			return fieldValue
    75  
    76  		default:
    77  			return string(fieldValue)
    78  		}
    79  	}
    80  }
    81  
    82  // 将map的数据按照fields进行过滤,只保留与表字段同名的数据
    83  func (bs *dbBase) filterFields(table string, data map[string]interface{}) map[string]interface{} {
    84  	if fields, err := bs.db.getTableFields(table); err == nil {
    85  		for k, _ := range data {
    86  			if _, ok := fields[k]; !ok {
    87  				delete(data, k)
    88  			}
    89  		}
    90  	}
    91  	return data
    92  }
    93  
    94  // 获得指定表表的数据结构,构造成map哈希表返回,其中键名为表字段名称,键值暂无用途(默认为字段数据类型).
    95  func (bs *dbBase) getTableFields(table string) (fields map[string]string, err error) {
    96  	// 缓存不存在时会查询数据表结构,缓存后不过期,直至程序重启(重新部署)
    97  	v := bs.cache.GetOrSetFunc("table_fields_"+table, func() interface{} {
    98  		result := (Result)(nil)
    99  		result, err = bs.GetAll(fmt.Sprintf(`SHOW COLUMNS FROM %s`, bs.db.quoteWord(table)))
   100  		if err != nil {
   101  			return nil
   102  		}
   103  		fields = make(map[string]string)
   104  		for _, m := range result {
   105  			fields[m["Field"].String()] = m["Type"].String()
   106  		}
   107  		return fields
   108  	}, 0)
   109  	if err == nil {
   110  		fields = v.(map[string]string)
   111  	}
   112  	return
   113  }
   114  
   115  /*
   116  // 获取当前数据库所有的表结构
   117  func (bs *dbBase) getTables() []string {
   118      if result, _ := bs.GetAll(`SHOW TABLES`); result != nil {
   119          array := make([]string, len(result))
   120          for i, m := range result {
   121              for _, v := range m {
   122                  array[i] = v.String()
   123                  break
   124              }
   125          }
   126          return array
   127      }
   128      return nil
   129  }
   130  */