diff --git a/g/database/gdb/gdb_base.go b/g/database/gdb/gdb_base.go index 4e6186570..6434fa3ac 100644 --- a/g/database/gdb/gdb_base.go +++ b/g/database/gdb/gdb_base.go @@ -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 += "=?" } } } diff --git a/g/database/gdb/gdb_func.go b/g/database/gdb/gdb_func.go index 92a1ac078..cd21f3e8b 100644 --- a/g/database/gdb/gdb_func.go +++ b/g/database/gdb/gdb_func.go @@ -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) diff --git a/g/database/gdb/gdb_unit_z_model_test.go b/g/database/gdb/gdb_unit_z_model_test.go index b23974d60..d74ff5354 100644 --- a/g/database/gdb/gdb_unit_z_model_test.go +++ b/g/database/gdb/gdb_unit_z_model_test.go @@ -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) diff --git a/g/internal/debug/stack.go b/g/internal/debug/stack.go index fb1539c5c..82e4a7aa5 100644 --- a/g/internal/debug/stack.go +++ b/g/internal/debug/stack.go @@ -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 diff --git a/g/test/gtest/gtest.go b/g/test/gtest/gtest.go index 4cf6699b8..61aaeaccb 100644 --- a/g/test/gtest/gtest.go +++ b/g/test/gtest/gtest.go @@ -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 is the pointer to testing.T of stdlib (*testing.T). // The parameter 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 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 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(``); 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 is nil. func isNil(value interface{}) bool { rv := reflect.ValueOf(value) diff --git a/geg/database/gdb/mysql/gdb_args_slice.go b/geg/database/gdb/mysql/gdb_args_slice.go index 9c7c568ad..fbc009f91 100644 --- a/geg/database/gdb/mysql/gdb_args_slice.go +++ b/geg/database/gdb/mysql/gdb_args_slice.go @@ -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() } diff --git a/geg/os/glog/glog_line2.go b/geg/os/glog/glog_line2.go index ade091755..2da381896 100644 --- a/geg/os/glog/glog_line2.go +++ b/geg/os/glog/glog_line2.go @@ -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) }