From be15f85eae631b343b9be8b1c5726c1039a3d906 Mon Sep 17 00:00:00 2001 From: John Date: Wed, 4 Dec 2019 16:04:52 +0800 Subject: [PATCH] remove sql.ErrNoRows error for select functions for gdb; improve configuration feature for gdb/glog/gview --- database/gdb/gdb.go | 3 ++- database/gdb/gdb_base.go | 15 ++++++++++----- database/gdb/gdb_config.go | 5 +++++ database/gdb/gdb_model.go | 10 ++++++++-- frame/gins/gins.go | 24 ++++++++++++++++++------ os/glog/glog_logger_config.go | 12 +++++++----- os/gview/gview_config.go | 7 +++++-- util/gutil/gutil_map.go | 12 ++++++------ 8 files changed, 61 insertions(+), 27 deletions(-) diff --git a/database/gdb/gdb.go b/database/gdb/gdb.go index 22d5f3a87..9136a94c9 100644 --- a/database/gdb/gdb.go +++ b/database/gdb/gdb.go @@ -88,6 +88,7 @@ type DB interface { GetLastSql() *Sql PrintQueriedSqls() SetLogger(logger *glog.Logger) + GetLogger() *glog.Logger SetMaxIdleConnCount(n int) SetMaxOpenConnCount(n int) SetMaxConnLifetime(d time.Duration) @@ -199,7 +200,7 @@ func New(name ...string) (db DB, err error) { debug: gtype.NewBool(), cache: gcache.New(), schema: gtype.NewString(), - logger: glog.DefaultLogger(), + logger: glog.New(), maxConnLifetime: gDEFAULT_CONN_MAX_LIFE_TIME, } switch node.Type { diff --git a/database/gdb/gdb_base.go b/database/gdb/gdb_base.go index d66a23122..e77d8698a 100644 --- a/database/gdb/gdb_base.go +++ b/database/gdb/gdb_base.go @@ -50,16 +50,16 @@ func (bs *dbBase) GetQueriedSqls() []*Sql { if bs.sqls == nil { return nil } - sqls := make([]*Sql, 0) + array := make([]*Sql, 0) bs.sqls.Prev() bs.sqls.RLockIteratorPrev(func(value interface{}) bool { if value == nil { return false } - sqls = append(sqls, value.(*Sql)) + array = append(array, value.(*Sql)) return true }) - return sqls + return array } // 打印已经执行的SQL列表(仅在debug=true时有效) @@ -219,6 +219,9 @@ func (bs *dbBase) GetStruct(pointer interface{}, query string, args ...interface if err != nil { return err } + if len(one) == 0 { + return sql.ErrNoRows + } return one.Struct(pointer) } @@ -228,6 +231,9 @@ func (bs *dbBase) GetStructs(pointer interface{}, query string, args ...interfac if err != nil { return err } + if len(all) == 0 { + return sql.ErrNoRows + } return all.Structs(pointer) } @@ -597,7 +603,7 @@ func (bs *dbBase) getCache() *gcache.Cache { // 将数据查询的列表数据*sql.Rows转换为Result类型 func (bs *dbBase) rowsToResult(rows *sql.Rows) (Result, error) { if !rows.Next() { - return nil, sql.ErrNoRows + return nil, nil } // 列信息列表, 名称与类型 columnTypes, err := rows.ColumnTypes() @@ -631,7 +637,6 @@ func (bs *dbBase) rowsToResult(rows *sql.Rows) (Result, error) { // 由于 sql.RawBytes 是slice类型, 这里必须使用值复制 v := make([]byte, len(column)) copy(v, column) - //fmt.Println(columns[i], types[i], string(v), v, bs.db.convertValue(v, types[i])) row[columns[i]] = gvar.New(bs.db.convertValue(v, types[i])) } } diff --git a/database/gdb/gdb_config.go b/database/gdb/gdb_config.go index 9d1c17113..279fd4003 100644 --- a/database/gdb/gdb_config.go +++ b/database/gdb/gdb_config.go @@ -119,6 +119,11 @@ func (bs *dbBase) SetLogger(logger *glog.Logger) { bs.logger = logger } +// 获得数据库Logger对象 +func (bs *dbBase) GetLogger() *glog.Logger { + return bs.logger +} + // 设置数据库连接池中空闲链接的大小 func (bs *dbBase) SetMaxIdleConnCount(n int) { bs.maxIdleConnCount = n diff --git a/database/gdb/gdb_model.go b/database/gdb/gdb_model.go index d9fa5ff8a..fca9a7b09 100644 --- a/database/gdb/gdb_model.go +++ b/database/gdb/gdb_model.go @@ -616,16 +616,22 @@ func (md *Model) Struct(pointer interface{}) error { if err != nil { return err } + if len(one) == 0 { + return sql.ErrNoRows + } return one.Struct(pointer) } // 链式操作,查询多条记录,并自动转换为指定的slice对象, 如: []struct/[]*struct。 func (md *Model) Structs(pointer interface{}) error { - r, err := md.All() + all, err := md.All() if err != nil { return err } - return r.Structs(pointer) + if len(all) == 0 { + return sql.ErrNoRows + } + return all.Structs(pointer) } // 链式操作,将结果转换为指定的struct/*struct/[]struct/[]*struct, diff --git a/frame/gins/gins.go b/frame/gins/gins.go index da9502142..452c08d12 100644 --- a/frame/gins/gins.go +++ b/frame/gins/gins.go @@ -28,11 +28,13 @@ import ( ) const ( - gFRAME_CORE_COMPONENT_NAME_VIEW = "gf.core.component.view" gFRAME_CORE_COMPONENT_NAME_REDIS = "gf.core.component.redis" gFRAME_CORE_COMPONENT_NAME_LOGGER = "gf.core.component.logger" gFRAME_CORE_COMPONENT_NAME_SERVER = "gf.core.component.server" + gFRAME_CORE_COMPONENT_NAME_VIEWER = "gf.core.component.viewer" gFRAME_CORE_COMPONENT_NAME_DATABASE = "gf.core.component.database" + gLOGGER_NODE_NAME = "logger" + gVIEWER_NODE_NAME = "viewer" ) var ( @@ -86,17 +88,17 @@ func View(name ...string) *gview.View { if len(name) > 0 && name[0] != "" { instanceName = name[0] } - instanceKey := fmt.Sprintf("%s.%s", gFRAME_CORE_COMPONENT_NAME_VIEW, instanceName) + instanceKey := fmt.Sprintf("%s.%s", gFRAME_CORE_COMPONENT_NAME_VIEWER, instanceName) return instances.GetOrSetFuncLock(instanceKey, func() interface{} { view := gview.Instance(instanceName) // To avoid file no found error while it's not necessary. if Config().Available() { var m map[string]interface{} // It firstly searches the configuration of the instance name. - if m = Config().GetMap(fmt.Sprintf(`viewer.%s`, instanceName)); m == nil { + if m = Config().GetMap(fmt.Sprintf(`%s.%s`, gVIEWER_NODE_NAME, instanceName)); m == nil { // If the configuration for the instance does not exist, // it uses the default view configuration. - m = Config().GetMap("viewer") + m = Config().GetMap(gVIEWER_NODE_NAME) } if m != nil { if err := view.SetConfigWithMap(m); err != nil { @@ -140,10 +142,10 @@ func Log(name ...string) *glog.Logger { if Config().Available() { var m map[string]interface{} // It firstly searches the configuration of the instance name. - if m = Config().GetMap(fmt.Sprintf(`logger.%s`, instanceName)); m == nil { + if m = Config().GetMap(fmt.Sprintf(`%s.%s`, gLOGGER_NODE_NAME, instanceName)); m == nil { // If the configuration for the instance does not exist, // it uses the default logging configuration. - m = Config().GetMap("logger") + m = Config().GetMap(gLOGGER_NODE_NAME) } if m != nil { if err := logger.SetConfigWithMap(m); err != nil { @@ -208,6 +210,16 @@ func Database(name ...string) gdb.DB { addConfigMonitor(instanceKey, config) if db, err := gdb.New(name...); err == nil { + // Initialize logger for ORM. + m := config.GetMap(fmt.Sprintf("database.%s", gLOGGER_NODE_NAME)) + if m == nil { + m = config.GetMap(gLOGGER_NODE_NAME) + } + if m != nil { + if err := db.GetLogger().SetConfigWithMap(m); err != nil { + glog.Panic(err) + } + } return db } else { glog.Panic(err) diff --git a/os/glog/glog_logger_config.go b/os/glog/glog_logger_config.go index ec924e750..e68e62342 100644 --- a/os/glog/glog_logger_config.go +++ b/os/glog/glog_logger_config.go @@ -11,6 +11,7 @@ import ( "github.com/gogf/gf/internal/intlog" "github.com/gogf/gf/os/gfile" "github.com/gogf/gf/util/gconv" + "github.com/gogf/gf/util/gutil" "io" "strings" ) @@ -66,14 +67,15 @@ func (l *Logger) SetConfigWithMap(m map[string]interface{}) error { return errors.New("configuration cannot be empty") } // Change string configuration to int value for level. - if v, ok := m["level"]; ok { - switch gconv.String(v) { + levelKey, levelValue := gutil.MapPossibleItemByKey(m, "level") + if levelValue != nil { + switch gconv.String(levelValue) { case "all": - m["level"] = LEVEL_ALL + m[levelKey] = LEVEL_ALL case "dev": - m["level"] = LEVEL_DEV + m[levelKey] = LEVEL_DEV case "prod": - m["level"] = LEVEL_PROD + m[levelKey] = LEVEL_PROD } } config := DefaultConfig() diff --git a/os/gview/gview_config.go b/os/gview/gview_config.go index 2df6f5f22..53f415fa9 100644 --- a/os/gview/gview_config.go +++ b/os/gview/gview_config.go @@ -15,6 +15,7 @@ import ( "github.com/gogf/gf/os/gres" "github.com/gogf/gf/os/gspath" "github.com/gogf/gf/util/gconv" + "github.com/gogf/gf/util/gutil" ) // Config is the configuration object for template engine. @@ -56,8 +57,10 @@ func (view *View) SetConfigWithMap(m map[string]interface{}) error { return errors.New("configuration cannot be empty") } // Most common used configuration support for single view path. - if m["paths"] == nil && m["path"] != nil { - m["paths"] = []interface{}{m["path"]} + k1, v1 := gutil.MapPossibleItemByKey(m, "paths") + _, v2 := gutil.MapPossibleItemByKey(m, "path") + if v1 == nil && v2 != nil { + m[k1] = []interface{}{v2} } config := Config{} err := gconv.Struct(m, &config) diff --git a/util/gutil/gutil_map.go b/util/gutil/gutil_map.go index d49c9afab..1ffe5b5ba 100644 --- a/util/gutil/gutil_map.go +++ b/util/gutil/gutil_map.go @@ -26,23 +26,23 @@ func MapCopy(data map[string]interface{}) (copy map[string]interface{}) { return } -// MapValueForPossibleKey tries to find the possible value for given key with or without +// MapPossibleItemByKey tries to find the possible key-value pair for given key with or without // cases or chars '-'/'_'/'.'/' '. // // Note that this function might be of low performance. -func MapPossibleValueForKey(data map[string]interface{}, key string) interface{} { +func MapPossibleItemByKey(data map[string]interface{}, key string) (string, interface{}) { if v, ok := data[key]; ok { - return v + return key, v } replacedKey := replaceCharReg.ReplaceAllString(key, "") if v, ok := data[replacedKey]; ok { - return v + return replacedKey, v } // Loop for check. for k, v := range data { if strings.EqualFold(replaceCharReg.ReplaceAllString(k, ""), replacedKey) { - return v + return k, v } } - return nil + return "", nil }