mirror of
https://gitee.com/johng/gf.git
synced 2024-11-30 03:07:45 +08:00
add GetVar function for package genv; add DryRun feature for package gdb
This commit is contained in:
parent
be2d4b080e
commit
7bcc596308
@ -69,7 +69,7 @@ We currently accept donation by Alipay/WechatPay, please note your github/gitee
|
||||
|1*1x|wechat|¥100.00|
|
||||
|[ywanbing](https://github.com/ywanbing)|wechat|¥66.66|
|
||||
|[侯哥](http://www.macnie.com)|wechat|¥10.00|
|
||||
|如果🍋|alipay|¥100.00| 错误的奶茶^_^
|
||||
|如果🍋|alipay|¥100.00| 错过的奶茶^_^
|
||||
|蔡蔡|wechat|¥666.00| gf真强大,让项目省心
|
||||
|
||||
|
||||
|
@ -89,6 +89,8 @@ type DB interface {
|
||||
SetSchema(schema string)
|
||||
GetSchema() string
|
||||
GetPrefix() string
|
||||
SetDryRun(dryrun bool)
|
||||
GetDryRun() bool
|
||||
SetLogger(logger *glog.Logger)
|
||||
GetLogger() *glog.Logger
|
||||
SetMaxIdleConnCount(n int)
|
||||
@ -124,6 +126,7 @@ type Core struct {
|
||||
debug *gtype.Bool // Enable debug mode for the database.
|
||||
cache *gcache.Cache // Cache manager.
|
||||
schema *gtype.String // Custom schema for this object.
|
||||
dryrun *gtype.Bool // Dry run.
|
||||
prefix string // Table prefix.
|
||||
logger *glog.Logger // Logger.
|
||||
maxIdleConnCount int // Max idle connection count.
|
||||
@ -234,6 +237,7 @@ func New(name ...string) (db DB, err error) {
|
||||
debug: gtype.NewBool(),
|
||||
cache: gcache.New(),
|
||||
schema: gtype.NewString(),
|
||||
dryrun: gtype.NewBool(),
|
||||
logger: glog.New(),
|
||||
prefix: node.Prefix,
|
||||
maxIdleConnCount: gDEFAULT_CONN_MAX_IDLE_COUNT,
|
||||
@ -401,5 +405,8 @@ func (c *Core) getSqlDb(master bool, schema ...string) (sqlDb *sql.DB, err error
|
||||
if node.Debug {
|
||||
c.DB.SetDebug(node.Debug)
|
||||
}
|
||||
if node.Debug {
|
||||
c.DB.SetDryRun(node.DryRun)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -99,7 +99,11 @@ func (c *Core) DoExec(link Link, sql string, args ...interface{}) (result sql.Re
|
||||
sql, args = c.DB.HandleSqlBeforeCommit(link, sql, args)
|
||||
if c.DB.GetDebug() {
|
||||
mTime1 := gtime.TimestampMilli()
|
||||
result, err = link.Exec(sql, args...)
|
||||
if !c.DB.GetDryRun() {
|
||||
result, err = link.Exec(sql, args...)
|
||||
} else {
|
||||
result = new(SqlResult)
|
||||
}
|
||||
mTime2 := gtime.TimestampMilli()
|
||||
s := &Sql{
|
||||
Sql: sql,
|
||||
@ -111,7 +115,11 @@ func (c *Core) DoExec(link Link, sql string, args ...interface{}) (result sql.Re
|
||||
}
|
||||
c.writeSqlToLogger(s)
|
||||
} else {
|
||||
result, err = link.Exec(sql, args...)
|
||||
if !c.DB.GetDryRun() {
|
||||
result, err = link.Exec(sql, args...)
|
||||
} else {
|
||||
result = new(SqlResult)
|
||||
}
|
||||
}
|
||||
return result, formatError(err, sql, args...)
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ type ConfigNode struct {
|
||||
Role string // (Optional, "master" in default) Node role, used for master-slave mode: master, slave.
|
||||
Debug bool // (Optional) Debug mode enables debug information logging and output.
|
||||
Prefix string // (Optional) Table prefix.
|
||||
DryRun bool // (Optional) Dry run, which does SELECT but no INSERT/UPDATE/DELETE statements.
|
||||
Weight int // (Optional) Weight for load balance calculating, it's useless if there's just one node.
|
||||
Charset string // (Optional, "utf8mb4" in default) Custom charset when operating on database.
|
||||
LinkInfo string // (Optional) Custom link information, when it is used, configuration Host/Port/User/Pass/Name are ignored.
|
||||
@ -142,24 +143,19 @@ func (c *Core) SetMaxConnLifetime(d time.Duration) {
|
||||
|
||||
// String returns the node as string.
|
||||
func (node *ConfigNode) String() string {
|
||||
if node.LinkInfo != "" {
|
||||
return node.LinkInfo
|
||||
}
|
||||
return fmt.Sprintf(
|
||||
`%s@%s:%s,%s,%s,%s,%s,%v,%d-%d-%d`,
|
||||
`%s@%s:%s,%s,%s,%s,%s,%v,%d-%d-%d#%s`,
|
||||
node.User, node.Host, node.Port,
|
||||
node.Name, node.Type, node.Role, node.Charset, node.Debug,
|
||||
node.MaxIdleConnCount,
|
||||
node.MaxOpenConnCount,
|
||||
node.MaxConnLifetime,
|
||||
node.LinkInfo,
|
||||
)
|
||||
}
|
||||
|
||||
// SetDebug enables/disables the debug mode.
|
||||
func (c *Core) SetDebug(debug bool) {
|
||||
if c.debug.Val() == debug {
|
||||
return
|
||||
}
|
||||
c.debug.Set(debug)
|
||||
}
|
||||
|
||||
@ -178,6 +174,16 @@ func (c *Core) GetPrefix() string {
|
||||
return c.prefix
|
||||
}
|
||||
|
||||
// SetDryRun enables/disables the DryRun feature.
|
||||
func (c *Core) SetDryRun(dryrun bool) {
|
||||
c.dryrun.Set(dryrun)
|
||||
}
|
||||
|
||||
// GetDryRun returns the DryRun value.
|
||||
func (c *Core) GetDryRun() bool {
|
||||
return c.dryrun.Val()
|
||||
}
|
||||
|
||||
// SetSchema changes the schema for this database connection object.
|
||||
// Importantly note that when schema configuration changed for the database,
|
||||
// it affects all operations on the database object in the future.
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/internal/intlog"
|
||||
"github.com/gogf/gf/text/gregex"
|
||||
"github.com/gogf/gf/text/gstr"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
@ -33,6 +34,10 @@ func (d *DriverMysql) Open(config *ConfigNode) (*sql.DB, error) {
|
||||
var source string
|
||||
if config.LinkInfo != "" {
|
||||
source = config.LinkInfo
|
||||
// Custom changing the schema in runtime.
|
||||
if config.Name != "" {
|
||||
source, _ = gregex.ReplaceString(`/([\w\.\-]+)+`, "/"+config.Name, source)
|
||||
}
|
||||
} else {
|
||||
source = fmt.Sprintf(
|
||||
"%s:%s@tcp(%s:%s)/%s?charset=%s&multiStatements=true&parseTime=true&loc=Local",
|
||||
|
@ -38,10 +38,16 @@ func (r *SqlResult) RowsAffected() (int64, error) {
|
||||
if r.affected > 0 {
|
||||
return r.affected, nil
|
||||
}
|
||||
if r.result == nil {
|
||||
return 0, nil
|
||||
}
|
||||
return r.result.RowsAffected()
|
||||
}
|
||||
|
||||
// see sql.Result.LastInsertId
|
||||
func (r *SqlResult) LastInsertId() (int64, error) {
|
||||
if r.result == nil {
|
||||
return 0, nil
|
||||
}
|
||||
return r.result.LastInsertId()
|
||||
}
|
||||
|
@ -9,11 +9,33 @@ package gdb
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
|
||||
"github.com/gogf/gf/encoding/gparser"
|
||||
)
|
||||
|
||||
// Chunk splits an Result into multiple Results,
|
||||
// the size of each array is determined by <size>.
|
||||
// The last chunk may contain less than size elements.
|
||||
func (r Result) Chunk(size int) []Result {
|
||||
if size < 1 {
|
||||
return nil
|
||||
}
|
||||
length := len(r)
|
||||
chunks := int(math.Ceil(float64(length) / float64(size)))
|
||||
var n []Result
|
||||
for i, end := 0, 0; chunks > 0; chunks-- {
|
||||
end = (i + 1) * size
|
||||
if end > length {
|
||||
end = length
|
||||
}
|
||||
n = append(n, r[i*size:end])
|
||||
i++
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// Json converts <r> to JSON format content.
|
||||
func (r Result) Json() string {
|
||||
content, _ := gparser.VarToJson(r.List())
|
||||
|
@ -2123,3 +2123,38 @@ func Test_Model_OmitEmpty_Time(t *testing.T) {
|
||||
t.Assert(n, 1)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Result_Chunk(t *testing.T) {
|
||||
table := createInitTable()
|
||||
defer dropTable(table)
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
r, err := db.Table(table).Order("id asc").All()
|
||||
t.Assert(err, nil)
|
||||
chunks := r.Chunk(3)
|
||||
t.Assert(len(chunks), 4)
|
||||
t.Assert(chunks[0][0]["id"].Int(), 1)
|
||||
t.Assert(chunks[1][0]["id"].Int(), 4)
|
||||
t.Assert(chunks[2][0]["id"].Int(), 7)
|
||||
t.Assert(chunks[3][0]["id"].Int(), 10)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Model_DryRun(t *testing.T) {
|
||||
table := createInitTable()
|
||||
defer dropTable(table)
|
||||
db.SetDryRun(true)
|
||||
defer db.SetDryRun(false)
|
||||
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
one, err := db.Table(table).FindOne(1)
|
||||
t.Assert(err, nil)
|
||||
t.Assert(one["id"], 1)
|
||||
})
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
r, err := db.Table(table).Data("passport", "port_1").WherePri(1).Update()
|
||||
t.Assert(err, nil)
|
||||
n, err := r.RowsAffected()
|
||||
t.Assert(err, nil)
|
||||
t.Assert(n, 0)
|
||||
})
|
||||
}
|
||||
|
@ -189,15 +189,9 @@ func (c *Client) DoRequest(method, url string, data ...interface{}) (resp *Clien
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
}
|
||||
// For server requests Host specifies the host on which the
|
||||
// URL is sought. Per RFC 2616, this is either the value of
|
||||
// the "Host" header or the host name given in the URL itself.
|
||||
// It may be of the form "host:port".
|
||||
//
|
||||
// For client requests Host optionally overrides the Host
|
||||
// header to send. If empty, the Request.Write method uses
|
||||
// the value of URL.Host.
|
||||
if host := req.Header.Get("Host"); host != "" {
|
||||
// It's necessary set the req.Host if you want to custom the host value of the request.
|
||||
// It uses the "Host" value of the header.
|
||||
if host := req.Header.Get("Host"); host != "" && req.Host == "" {
|
||||
req.Host = host
|
||||
}
|
||||
// Custom Cookie.
|
||||
|
@ -107,7 +107,7 @@ func (r *Response) WriteJson(content interface{}) error {
|
||||
switch content.(type) {
|
||||
case string, []byte:
|
||||
r.Header().Set("Content-Type", "application/json")
|
||||
r.Write(content)
|
||||
r.Write(gconv.String(content))
|
||||
return nil
|
||||
}
|
||||
// Else use json.Marshal function to encode the parameter.
|
||||
@ -139,7 +139,7 @@ func (r *Response) WriteJsonP(content interface{}) error {
|
||||
switch content.(type) {
|
||||
case string, []byte:
|
||||
r.Header().Set("Content-Type", "application/json")
|
||||
r.Write(content)
|
||||
r.Write(gconv.String(content))
|
||||
return nil
|
||||
}
|
||||
// Else use json.Marshal function to encode the parameter.
|
||||
@ -179,7 +179,7 @@ func (r *Response) WriteXml(content interface{}, rootTag ...string) error {
|
||||
switch content.(type) {
|
||||
case string, []byte:
|
||||
r.Header().Set("Content-Type", "application/xml")
|
||||
r.Write(content)
|
||||
r.Write(gconv.String(content))
|
||||
return nil
|
||||
}
|
||||
// Else use gparser.VarToXml function to encode the parameter.
|
||||
|
@ -7,7 +7,10 @@
|
||||
// Package genv provides operations for environment variables of system.
|
||||
package genv
|
||||
|
||||
import "os"
|
||||
import (
|
||||
"github.com/gogf/gf/container/gvar"
|
||||
"os"
|
||||
)
|
||||
import "strings"
|
||||
|
||||
// All returns a copy of strings representing the environment,
|
||||
@ -37,6 +40,17 @@ func Get(key string, def ...string) string {
|
||||
return v
|
||||
}
|
||||
|
||||
// GetVar creates and returns a Var with the value of the environment variable
|
||||
// named by the <key>. It uses the given <def> if the variable does not exist
|
||||
// in the environment.
|
||||
func GetVar(key string, def ...interface{}) *gvar.Var {
|
||||
v, ok := os.LookupEnv(key)
|
||||
if !ok && len(def) > 0 {
|
||||
return gvar.New(def[0])
|
||||
}
|
||||
return gvar.New(v)
|
||||
}
|
||||
|
||||
// Set sets the value of the environment variable named by the <key>.
|
||||
// It returns an error, if any.
|
||||
func Set(key, value string) error {
|
||||
|
Loading…
Reference in New Issue
Block a user