mirror of
https://gitee.com/johng/gf
synced 2026-06-06 16:21:40 +08:00
improve internal/debug, gdb packages
This commit is contained in:
@ -12,11 +12,12 @@ import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/text/gstr"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/g/text/gstr"
|
||||
|
||||
"github.com/gogf/gf/g/container/gvar"
|
||||
"github.com/gogf/gf/g/os/gcache"
|
||||
"github.com/gogf/gf/g/os/gtime"
|
||||
@ -30,8 +31,8 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
// 用于可转义的单词的识别正则对象
|
||||
wordReg = regexp.MustCompile(`^[a-zA-Z0-9\-_]+$`)
|
||||
wordReg = regexp.MustCompile(`^[a-zA-Z0-9\-_]+$`)
|
||||
lastOperatorReg = regexp.MustCompile(`[<>=]+\s*$`)
|
||||
)
|
||||
|
||||
// 获取最近一条执行的sql
|
||||
@ -698,12 +699,12 @@ func (bs *dbBase) formatWhere(where interface{}, args []interface{}) (newWhere s
|
||||
newWhere = buffer.String()
|
||||
// 查询条件参数处理,主要处理slice参数类型
|
||||
if len(newArgs) > 0 {
|
||||
// 支持例如 Where/And/Or("uid", 1) 这种格式
|
||||
// 支持例如 Where/And/Or("uid", 1) , Where/And/Or("uid>=", 1) 这种格式
|
||||
if gstr.Pos(newWhere, "?") == -1 {
|
||||
if gstr.Pos(newWhere, "<") == -1 && gstr.Pos(newWhere, ">") == -1 && gstr.Pos(newWhere, "=") == -1 {
|
||||
newWhere += "=?"
|
||||
} else {
|
||||
if lastOperatorReg.MatchString(newWhere) {
|
||||
newWhere += "?"
|
||||
} else if wordReg.MatchString(newWhere) {
|
||||
newWhere += "=?"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,6 +43,9 @@ func formatQuery(query string, args []interface{}) (newQuery string, newArgs []i
|
||||
switch kind {
|
||||
// '?'占位符支持slice类型, 这里会将slice参数拆散,并更新原有占位符'?'为多个'?',使用','符号连接。
|
||||
case reflect.Slice, reflect.Array:
|
||||
if rv.Len() == 0 {
|
||||
continue
|
||||
}
|
||||
// 不拆分[]byte类型
|
||||
if _, ok := arg.([]byte); ok {
|
||||
newArgs = append(newArgs, arg)
|
||||
|
||||
@ -641,6 +641,12 @@ func Test_Model_Where(t *testing.T) {
|
||||
gtest.AssertGT(len(result), 0)
|
||||
gtest.Assert(result["id"].Int(), 3)
|
||||
})
|
||||
gtest.Case(t, func() {
|
||||
result, err := db.Table(table).Where("id=3", g.Slice{}).One()
|
||||
gtest.Assert(err, nil)
|
||||
gtest.AssertGT(len(result), 0)
|
||||
gtest.Assert(result["id"].Int(), 3)
|
||||
})
|
||||
gtest.Case(t, func() {
|
||||
result, err := db.Table(table).Where("id=?", g.Slice{3}).One()
|
||||
gtest.Assert(err, nil)
|
||||
|
||||
@ -60,6 +60,12 @@ func StackWithFilter(filter string, skip ...int) string {
|
||||
if goRootForFilter != "" && len(file) >= len(goRootForFilter) && file[0:len(goRootForFilter)] == goRootForFilter {
|
||||
continue
|
||||
}
|
||||
if filter != "" && strings.Contains(file, filter) {
|
||||
continue
|
||||
}
|
||||
if strings.Contains(file, gFILTER_KEY) {
|
||||
continue
|
||||
}
|
||||
if fn := runtime.FuncForPC(pc); fn == nil {
|
||||
name = "unknown"
|
||||
} else {
|
||||
@ -92,6 +98,12 @@ func CallerWithFilter(filter string, skip ...int) string {
|
||||
}
|
||||
for i := callerFromIndex(filter) + number; i < gMAX_DEPTH; i++ {
|
||||
if _, file, line, ok := runtime.Caller(i); ok {
|
||||
if filter != "" && strings.Contains(file, filter) {
|
||||
continue
|
||||
}
|
||||
if strings.Contains(file, gFILTER_KEY) {
|
||||
continue
|
||||
}
|
||||
return fmt.Sprintf(`%s:%d`, file, line)
|
||||
} else {
|
||||
break
|
||||
|
||||
@ -11,21 +11,24 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/g/internal/debug"
|
||||
|
||||
"github.com/gogf/gf/g/util/gconv"
|
||||
)
|
||||
|
||||
const (
|
||||
gPATH_FILTER_KEY = "/g/test/gtest/gtest"
|
||||
)
|
||||
|
||||
// Case creates an unit test case.
|
||||
// The parameter <t> is the pointer to testing.T of stdlib (*testing.T).
|
||||
// The parameter <f> is the callback function for unit test case.
|
||||
func Case(t *testing.T, f func()) {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n%s", err, getStack())
|
||||
fmt.Fprintf(os.Stderr, "%v\n%s", err, debug.StackWithFilter(gPATH_FILTER_KEY))
|
||||
t.Fail()
|
||||
}
|
||||
}()
|
||||
@ -262,7 +265,7 @@ func Error(message ...interface{}) {
|
||||
|
||||
// Fatal prints <message> to stderr and exit the process.
|
||||
func Fatal(message ...interface{}) {
|
||||
fmt.Fprintf(os.Stderr, "[FATAL] %s\n%s", fmt.Sprint(message...), getStack())
|
||||
fmt.Fprintf(os.Stderr, "[FATAL] %s\n%s", fmt.Sprint(message...), debug.StackWithFilter(gPATH_FILTER_KEY))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@ -305,53 +308,6 @@ func compareMap(value, expect interface{}) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// getStack returns the caller stack content from getStack.
|
||||
// The parameter <skip> indicates the skip count of the caller stack from getStack.
|
||||
func getStack(skip ...int) string {
|
||||
customSkip := 0
|
||||
if len(skip) > 0 {
|
||||
customSkip = skip[0]
|
||||
}
|
||||
stack := ""
|
||||
index := 1
|
||||
from := 0
|
||||
// Ignore current gtest lines and find the beginning index of caller file.
|
||||
for i := 0; i < 10; i++ {
|
||||
if _, file, _, ok := runtime.Caller(i); ok {
|
||||
if reg, _ := regexp.Compile(`gtest\.go$`); !reg.MatchString(file) {
|
||||
from = i
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
// Converting all file separator to "/".
|
||||
goRoot := runtime.GOROOT()
|
||||
if goRoot != "" {
|
||||
goRoot = strings.Replace(goRoot, "\\", "/", -1)
|
||||
goRoot = regexp.QuoteMeta(goRoot)
|
||||
}
|
||||
for i := from + customSkip; i < 10000; i++ {
|
||||
if _, file, cline, ok := runtime.Caller(i); ok && file != "" {
|
||||
if reg, _ := regexp.Compile(`<autogenerated>`); reg.MatchString(file) {
|
||||
continue
|
||||
}
|
||||
if reg, _ := regexp.Compile(`gtest\.go$`); reg.MatchString(file) {
|
||||
continue
|
||||
}
|
||||
if goRoot != "" {
|
||||
if reg, _ := regexp.Compile("^" + goRoot); reg.MatchString(file) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
stack += fmt.Sprintf(`%d. %s:%d%s`, index, file, cline, "\n")
|
||||
index++
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return stack
|
||||
}
|
||||
|
||||
// isNil checks whether <value> is nil.
|
||||
func isNil(value interface{}) bool {
|
||||
rv := reflect.ValueOf(value)
|
||||
|
||||
@ -17,4 +17,7 @@ func main() {
|
||||
"id in(?)": g.Slice{1, 2, 3},
|
||||
}
|
||||
db.Table("user").Where(conditions).OrderBy("id asc").All()
|
||||
|
||||
var params []interface{}
|
||||
db.Table("user").Where("1=1", params).OrderBy("id asc").All()
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ import (
|
||||
)
|
||||
|
||||
func PrintLog(content string) {
|
||||
glog.Skip(1).Line().Println("line number with skip:", content)
|
||||
glog.Skip(0).Line().Println("line number with skip:", content)
|
||||
glog.Line(true).Println("line number without skip:", content)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user