mirror of
https://gitee.com/johng/gf
synced 2026-07-08 22:40:30 +08:00
add function Close for DB for package gdb
This commit is contained in:
@ -73,6 +73,14 @@ type DB interface {
|
||||
// Also see Core.Ctx.
|
||||
Ctx(ctx context.Context) DB
|
||||
|
||||
// Close closes the database and prevents new queries from starting.
|
||||
// Close then waits for all queries that have started processing on the server
|
||||
// to finish.
|
||||
//
|
||||
// It is rare to Close a DB, as the DB handle is meant to be
|
||||
// long-lived and shared between many goroutines.
|
||||
Close(ctx context.Context) error
|
||||
|
||||
// ===========================================================================
|
||||
// Query APIs.
|
||||
// ===========================================================================
|
||||
@ -94,7 +102,7 @@ type DB interface {
|
||||
Delete(table string, condition interface{}, args ...interface{}) (sql.Result, error) // See Core.Delete.
|
||||
|
||||
// ===========================================================================
|
||||
// Internal APIs for CURD, which can be overwrote for custom CURD implements.
|
||||
// Internal APIs for CURD, which can be overwritten by custom CURD implements.
|
||||
// ===========================================================================
|
||||
|
||||
DoGetAll(ctx context.Context, link Link, sql string, args ...interface{}) (result Result, err error) // See Core.DoGetAll.
|
||||
@ -179,6 +187,7 @@ type Core struct {
|
||||
group string // Configuration group name.
|
||||
debug *gtype.Bool // Enable debug mode for the database, which can be changed in runtime.
|
||||
cache *gcache.Cache // Cache manager, SQL result cache only.
|
||||
links *gmap.StrAnyMap // links caches all created links by node.
|
||||
schema *gtype.String // Custom schema for this object.
|
||||
logger *glog.Logger // Logger for logging functionality.
|
||||
config *ConfigNode // Current config node.
|
||||
@ -302,9 +311,6 @@ var (
|
||||
// in the field name as it conflicts with "db.table.field" pattern in SOME situations.
|
||||
regularFieldNameWithoutDotRegPattern = `^[\w\-]+$`
|
||||
|
||||
// internalCache is the memory cache for internal usage.
|
||||
internalCache = gcache.New()
|
||||
|
||||
// tableFieldsMap caches the table information retrived from database.
|
||||
tableFieldsMap = gmap.New(true)
|
||||
|
||||
@ -347,6 +353,7 @@ func New(group ...string) (db DB, err error) {
|
||||
group: groupName,
|
||||
debug: gtype.NewBool(),
|
||||
cache: gcache.New(),
|
||||
links: gmap.NewStrAnyMap(true),
|
||||
schema: gtype.NewString(),
|
||||
logger: glog.New(),
|
||||
config: node,
|
||||
@ -441,7 +448,7 @@ func getConfigNodeByWeight(cg ConfigGroup) *ConfigNode {
|
||||
for i := 0; i < len(cg); i++ {
|
||||
total += cg[i].Weight * 100
|
||||
}
|
||||
// If total is 0 means all of the nodes have no weight attribute configured.
|
||||
// If total is 0 means all the nodes have no weight attribute configured.
|
||||
// It then defaults each node's weight attribute to 1.
|
||||
if total == 0 {
|
||||
for i := 0; i < len(cg); i++ {
|
||||
@ -490,7 +497,7 @@ func (c *Core) getSqlDb(master bool, schema ...string) (sqlDb *sql.DB, err error
|
||||
node = &n
|
||||
}
|
||||
// Cache the underlying connection pool object by node.
|
||||
v, _ := internalCache.GetOrSetFuncLock(node.String(), func() (interface{}, error) {
|
||||
v := c.links.GetOrSetFuncLock(node.String(), func() interface{} {
|
||||
intlog.Printf(
|
||||
c.db.GetCtx(),
|
||||
`open new connection, master:%#v, config:%#v, node:%#v`,
|
||||
@ -510,7 +517,7 @@ func (c *Core) getSqlDb(master bool, schema ...string) (sqlDb *sql.DB, err error
|
||||
|
||||
sqlDb, err = c.db.Open(node)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil
|
||||
}
|
||||
|
||||
if c.config.MaxIdleConnCount > 0 {
|
||||
@ -534,8 +541,8 @@ func (c *Core) getSqlDb(master bool, schema ...string) (sqlDb *sql.DB, err error
|
||||
} else {
|
||||
sqlDb.SetConnMaxLifetime(defaultMaxConnLifeTime)
|
||||
}
|
||||
return sqlDb, nil
|
||||
}, 0)
|
||||
return sqlDb
|
||||
})
|
||||
if v != nil && sqlDb == nil {
|
||||
sqlDb = v.(*sql.DB)
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/errors/gcode"
|
||||
"github.com/gogf/gf/internal/intlog"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
@ -95,6 +96,27 @@ func (c *Core) GetCtxTimeout(timeoutType int, ctx context.Context) (context.Cont
|
||||
return ctx, func() {}
|
||||
}
|
||||
|
||||
// Close closes the database and prevents new queries from starting.
|
||||
// Close then waits for all queries that have started processing on the server
|
||||
// to finish.
|
||||
//
|
||||
// It is rare to Close a DB, as the DB handle is meant to be
|
||||
// long-lived and shared between many goroutines.
|
||||
func (c *Core) Close(ctx context.Context) (err error) {
|
||||
c.links.LockFunc(func(m map[string]interface{}) {
|
||||
for k, v := range m {
|
||||
if db, ok := v.(*sql.DB); ok {
|
||||
err = db.Close()
|
||||
intlog.Printf(ctx, `close link: %s, err: %v`, k, err)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Master creates and returns a connection from master node if master-slave configured.
|
||||
// It returns the default connection if master-slave not configured.
|
||||
func (c *Core) Master(schema ...string) (*sql.DB, error) {
|
||||
|
||||
@ -236,34 +236,6 @@ FROM USER_TAB_COLUMNS WHERE TABLE_NAME = '%s' ORDER BY COLUMN_ID`,
|
||||
return
|
||||
}
|
||||
|
||||
func (d *DriverOracle) getTableUniqueIndex(table string) (fields map[string]map[string]string, err error) {
|
||||
table = strings.ToUpper(table)
|
||||
v, _ := internalCache.GetOrSetFunc(
|
||||
"table_unique_index_"+table,
|
||||
func() (interface{}, error) {
|
||||
res := (Result)(nil)
|
||||
res, err = d.db.GetAll(fmt.Sprintf(`
|
||||
SELECT INDEX_NAME,COLUMN_NAME,CHAR_LENGTH FROM USER_IND_COLUMNS
|
||||
WHERE TABLE_NAME = '%s'
|
||||
AND INDEX_NAME IN(SELECT INDEX_NAME FROM USER_INDEXES WHERE TABLE_NAME='%s' AND UNIQUENESS='UNIQUE')
|
||||
ORDER BY INDEX_NAME,COLUMN_POSITION`, table, table))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fields := make(map[string]map[string]string)
|
||||
for _, v := range res {
|
||||
mm := make(map[string]string)
|
||||
mm[v["COLUMN_NAME"].String()] = v["CHAR_LENGTH"].String()
|
||||
fields[v["INDEX_NAME"].String()] = mm
|
||||
}
|
||||
return fields, nil
|
||||
}, 0)
|
||||
if err == nil {
|
||||
fields = v.(map[string]map[string]string)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DoInsert inserts or updates data for given table.
|
||||
// This function is usually used for custom interface definition, you do not need call it manually.
|
||||
// The parameter `data` can be type of map/gmap/struct/*struct/[]map/[]struct, etc.
|
||||
|
||||
Reference in New Issue
Block a user