From 88d07058a56974878603fe26758fb5690a6a7d00 Mon Sep 17 00:00:00 2001 From: Yang Luo Date: Fri, 19 May 2017 22:19:31 +0800 Subject: [PATCH 01/38] Fix the new repo address for casbin. --- .travis.yml | 2 +- plugins/authz/authz.go | 4 ++-- plugins/authz/authz_test.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index aa88a44d..2937e6e8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,7 +34,7 @@ install: - go get github.com/cloudflare/golz4 - go get github.com/gogo/protobuf/proto - go get github.com/Knetic/govaluate - - go get github.com/hsluoyz/casbin + - go get github.com/casbin/casbin - go get -u honnef.co/go/tools/cmd/gosimple - go get -u github.com/mdempsky/unconvert - go get -u github.com/gordonklaus/ineffassign diff --git a/plugins/authz/authz.go b/plugins/authz/authz.go index 709a613a..9dc0db76 100644 --- a/plugins/authz/authz.go +++ b/plugins/authz/authz.go @@ -17,7 +17,7 @@ // import( // "github.com/astaxie/beego" // "github.com/astaxie/beego/plugins/authz" -// "github.com/hsluoyz/casbin" +// "github.com/casbin/casbin" // ) // // func main(){ @@ -42,7 +42,7 @@ package authz import ( "github.com/astaxie/beego" "github.com/astaxie/beego/context" - "github.com/hsluoyz/casbin" + "github.com/casbin/casbin" "net/http" ) diff --git a/plugins/authz/authz_test.go b/plugins/authz/authz_test.go index 4003582c..49aed84c 100644 --- a/plugins/authz/authz_test.go +++ b/plugins/authz/authz_test.go @@ -18,7 +18,7 @@ import ( "github.com/astaxie/beego" "github.com/astaxie/beego/context" "github.com/astaxie/beego/plugins/auth" - "github.com/hsluoyz/casbin" + "github.com/casbin/casbin" "net/http" "net/http/httptest" "testing" From 0ea34fff2709a56a0e22fea9b2bd4c249feb4634 Mon Sep 17 00:00:00 2001 From: Jia Li Ong Date: Thu, 1 Jun 2017 17:48:48 +0800 Subject: [PATCH 02/38] Provide permission to access old log files to everyone --- logs/file.go | 2 +- logs/file_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/logs/file.go b/logs/file.go index 1c2db882..33fee1cf 100644 --- a/logs/file.go +++ b/logs/file.go @@ -271,7 +271,7 @@ func (w *fileLogWriter) doRotate(logTime time.Time) error { if err != nil { goto RESTART_LOGGER } - err = os.Chmod(fName, os.FileMode(0440)) + err = os.Chmod(fName, os.FileMode(0444)) // re-start logger RESTART_LOGGER: diff --git a/logs/file_test.go b/logs/file_test.go index f345ff20..ba0850b1 100644 --- a/logs/file_test.go +++ b/logs/file_test.go @@ -175,7 +175,7 @@ func TestFileRotate_06(t *testing.T) { //test file mode log.Emergency("emergency") rotateName := "test3" + fmt.Sprintf(".%s.%03d", time.Now().Format("2006-01-02"), 1) + ".log" s, _ := os.Lstat(rotateName) - if s.Mode() != 0440 { + if s.Mode() != 0444 { os.Remove(rotateName) os.Remove("test3.log") t.Fatal("rotate file mode error") From d15dd2795c962b9fc7c5e55e1c7ff7ebdeddce44 Mon Sep 17 00:00:00 2001 From: Gerson Alexander Pardo Gamez Date: Sat, 3 Jun 2017 15:24:45 -0500 Subject: [PATCH 03/38] added statusCode in FilterMonitorFunc --- admin.go | 6 +++--- router.go | 6 +++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/admin.go b/admin.go index 875cd0e8..8d28c10c 100644 --- a/admin.go +++ b/admin.go @@ -37,7 +37,7 @@ var beeAdminApp *adminApp // FilterMonitorFunc is default monitor filter when admin module is enable. // if this func returns, admin module records qbs for this request by condition of this function logic. // usage: -// func MyFilterMonitor(method, requestPath string, t time.Duration) bool { +// func MyFilterMonitor(method, requestPath string, t time.Duration, statusCode int) bool { // if method == "POST" { // return false // } @@ -50,7 +50,7 @@ var beeAdminApp *adminApp // return true // } // beego.FilterMonitorFunc = MyFilterMonitor. -var FilterMonitorFunc func(string, string, time.Duration) bool +var FilterMonitorFunc func(string, string, time.Duration, int) bool func init() { beeAdminApp = &adminApp{ @@ -62,7 +62,7 @@ func init() { beeAdminApp.Route("/healthcheck", healthcheck) beeAdminApp.Route("/task", taskStatus) beeAdminApp.Route("/listconf", listConf) - FilterMonitorFunc = func(string, string, time.Duration) bool { return true } + FilterMonitorFunc = func(string, string, time.Duration, int) bool { return true } } // AdminIndex is the default http.Handler for admin module. diff --git a/router.go b/router.go index 72476ae8..c6da4f9b 100644 --- a/router.go +++ b/router.go @@ -849,7 +849,11 @@ Admin: //admin module record QPS if BConfig.Listen.EnableAdmin { timeDur := time.Since(startTime) - if FilterMonitorFunc(r.Method, r.URL.Path, timeDur) { + statusCode := context.ResponseWriter.Status + if statusCode == 0 { + statusCode = 200 + } + if FilterMonitorFunc(r.Method, r.URL.Path, timeDur, statusCode) { if runRouter != nil { go toolbox.StatisticsMap.AddStatistics(r.Method, r.URL.Path, runRouter.Name(), timeDur) } else { From 7f2e3feb3c485cebd5b8c6ee309884160d6cad37 Mon Sep 17 00:00:00 2001 From: Gerson Alexander Pardo Gamez Date: Mon, 5 Jun 2017 18:21:31 -0500 Subject: [PATCH 04/38] added pattern to FilterMonitorFunc --- admin.go | 4 ++-- router.go | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/admin.go b/admin.go index 8d28c10c..e6f9c3f9 100644 --- a/admin.go +++ b/admin.go @@ -50,7 +50,7 @@ var beeAdminApp *adminApp // return true // } // beego.FilterMonitorFunc = MyFilterMonitor. -var FilterMonitorFunc func(string, string, time.Duration, int) bool +var FilterMonitorFunc func(string, string, time.Duration, string, int) bool func init() { beeAdminApp = &adminApp{ @@ -62,7 +62,7 @@ func init() { beeAdminApp.Route("/healthcheck", healthcheck) beeAdminApp.Route("/task", taskStatus) beeAdminApp.Route("/listconf", listConf) - FilterMonitorFunc = func(string, string, time.Duration, int) bool { return true } + FilterMonitorFunc = func(string, string, time.Duration, string, int) bool { return true } } // AdminIndex is the default http.Handler for admin module. diff --git a/router.go b/router.go index c6da4f9b..874fb109 100644 --- a/router.go +++ b/router.go @@ -849,11 +849,15 @@ Admin: //admin module record QPS if BConfig.Listen.EnableAdmin { timeDur := time.Since(startTime) + pattern := "" + if routerInfo != nil { + pattern = routerInfo.pattern + } statusCode := context.ResponseWriter.Status if statusCode == 0 { statusCode = 200 } - if FilterMonitorFunc(r.Method, r.URL.Path, timeDur, statusCode) { + if FilterMonitorFunc(r.Method, r.URL.Path, timeDur, pattern, statusCode) { if runRouter != nil { go toolbox.StatisticsMap.AddStatistics(r.Method, r.URL.Path, runRouter.Name(), timeDur) } else { From 0240e182c68574b1d56bff7b053f350a7ce063af Mon Sep 17 00:00:00 2001 From: eyalpost Date: Fri, 9 Jun 2017 10:15:36 +0300 Subject: [PATCH 05/38] correctly handle multiple params with same type --- parser.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/parser.go b/parser.go index a9cfd894..fda83cb7 100644 --- a/parser.go +++ b/parser.go @@ -135,15 +135,16 @@ func parserComments(f *ast.FuncDecl, controllerName, pkgpath string) error { func buildMethodParams(funcParams []*ast.Field, pc *parsedComment) []*param.MethodParam { result := make([]*param.MethodParam, 0, len(funcParams)) for _, fparam := range funcParams { - methodParam := buildMethodParam(fparam, pc) - result = append(result, methodParam) + for _, pName := range fparam.Names { + methodParam := buildMethodParam(fparam, pName.Name, pc) + result = append(result, methodParam) + } } return result } -func buildMethodParam(fparam *ast.Field, pc *parsedComment) *param.MethodParam { +func buildMethodParam(fparam *ast.Field, name string, pc *parsedComment) *param.MethodParam { options := []param.MethodParamOption{} - name := fparam.Names[0].Name if cparam, ok := pc.params[name]; ok { //Build param from comment info name = cparam.name From 8b504e7d51245c987fbc62591c2e53e43a71e3dd Mon Sep 17 00:00:00 2001 From: eyalpost Date: Mon, 12 Jun 2017 21:05:40 +0300 Subject: [PATCH 06/38] incorrect error rendering (wrong status) --- context/output.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/context/output.go b/context/output.go index cf9e7a7e..61ce8cc7 100644 --- a/context/output.go +++ b/context/output.go @@ -177,7 +177,7 @@ func jsonRenderer(value interface{}) Renderer { func errorRenderer(err error) Renderer { return rendererFunc(func(ctx *Context) { ctx.Output.SetStatus(500) - ctx.WriteString(err.Error()) + ctx.Output.Body([]byte(err.Error())) }) } From 55e6c15073cf127a0a9a3af3fbc68e85c87f7d93 Mon Sep 17 00:00:00 2001 From: huwenbo Date: Tue, 13 Jun 2017 15:19:51 +0800 Subject: [PATCH 07/38] fix panic: sync: negative WaitGroup counter --- grace/conn.go | 13 ++++++++++++- grace/listener.go | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/grace/conn.go b/grace/conn.go index 6807e1ac..f5d2b236 100644 --- a/grace/conn.go +++ b/grace/conn.go @@ -3,11 +3,14 @@ package grace import ( "errors" "net" + "sync" ) type graceConn struct { net.Conn server *Server + m sync.Mutex + closed bool } func (c graceConn) Close() (err error) { @@ -23,6 +26,14 @@ func (c graceConn) Close() (err error) { } } }() + + c.m.Lock() + if c.closed { + c.m.Unlock() + return + } c.server.wg.Done() + c.closed = true + c.m.Unlock() return c.Conn.Close() -} +} \ No newline at end of file diff --git a/grace/listener.go b/grace/listener.go index 823d3cce..7ede63a3 100644 --- a/grace/listener.go +++ b/grace/listener.go @@ -37,7 +37,7 @@ func (gl *graceListener) Accept() (c net.Conn, err error) { tc.SetKeepAlive(true) tc.SetKeepAlivePeriod(3 * time.Minute) - c = graceConn{ + c = &graceConn{ Conn: tc, server: gl.server, } From 3d9286f089c5661641da9651cf56bd4f1666d4db Mon Sep 17 00:00:00 2001 From: huwenbo Date: Tue, 13 Jun 2017 15:34:57 +0800 Subject: [PATCH 08/38] fix panic: sync: negative WaitGroup counter --- grace/conn.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grace/conn.go b/grace/conn.go index f5d2b236..4553e182 100644 --- a/grace/conn.go +++ b/grace/conn.go @@ -36,4 +36,4 @@ func (c graceConn) Close() (err error) { c.closed = true c.m.Unlock() return c.Conn.Close() -} \ No newline at end of file +} From 2b00b7d66dd6582405aaae64024bbb9590cc9604 Mon Sep 17 00:00:00 2001 From: huwenbo Date: Tue, 13 Jun 2017 20:15:43 +0800 Subject: [PATCH 09/38] fix panic: sync: negative WaitGroup counter --- grace/conn.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grace/conn.go b/grace/conn.go index 4553e182..6f52045f 100644 --- a/grace/conn.go +++ b/grace/conn.go @@ -13,7 +13,7 @@ type graceConn struct { closed bool } -func (c graceConn) Close() (err error) { +func (c *graceConn) Close() (err error) { defer func() { if r := recover(); r != nil { switch x := r.(type) { From a87c1c5e8e8eeb2838e6716b9b73bd2f90314612 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Thu, 15 Jun 2017 17:36:37 +0800 Subject: [PATCH 10/38] AddAPPStartHook func modify --- beego.go | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/beego.go b/beego.go index 22079a20..218fded8 100644 --- a/beego.go +++ b/beego.go @@ -40,9 +40,9 @@ var ( // AddAPPStartHook is used to register the hookfunc // The hookfuncs will run in beego.Run() -// such as sessionInit, middlerware start, buildtemplate, admin start -func AddAPPStartHook(hf hookfunc) { - hooks = append(hooks, hf) +// such as initiating session , starting middleware , building template, starting admin control and so on. +func AddAPPStartHook(hf ...hookfunc) { + hooks = append(hooks, hf...) } // Run beego application. @@ -69,12 +69,14 @@ func Run(params ...string) { func initBeforeHTTPRun() { //init hooks - AddAPPStartHook(registerMime) - AddAPPStartHook(registerDefaultErrorHandler) - AddAPPStartHook(registerSession) - AddAPPStartHook(registerTemplate) - AddAPPStartHook(registerAdmin) - AddAPPStartHook(registerGzip) + AddAPPStartHook( + registerMime, + registerDefaultErrorHandler, + registerSession, + registerTemplate, + registerAdmin, + registerGzip, + ) for _, hk := range hooks { if err := hk(); err != nil { From 79f60274a0e15ac85483f5a21c9d6ce70e0ff551 Mon Sep 17 00:00:00 2001 From: moqiancong Date: Fri, 16 Jun 2017 01:26:55 +0800 Subject: [PATCH 11/38] fix cache/memory fatal error: concurrent map iteration and map write --- cache/memory.go | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/cache/memory.go b/cache/memory.go index fff2ebbb..57e868cf 100644 --- a/cache/memory.go +++ b/cache/memory.go @@ -217,26 +217,31 @@ func (bc *MemoryCache) vaccuum() { if bc.items == nil { return } - for name := range bc.items { - bc.itemExpired(name) + if keys := bc.expiredKeys(); len(keys) != 0 { + bc.clearItems(keys) } } } -// itemExpired returns true if an item is expired. -func (bc *MemoryCache) itemExpired(name string) bool { +// expiredKeys returns key list which are expired. +func (bc *MemoryCache) expiredKeys() (keys []string) { + bc.RLock() + defer bc.RUnlock() + for key, itm := range bc.items { + if itm.isExpire() { + keys = append(keys, key) + } + } + return +} + +// clearItems removes all the items which key in keys. +func (bc *MemoryCache) clearItems(keys []string) { bc.Lock() defer bc.Unlock() - - itm, ok := bc.items[name] - if !ok { - return true + for _, key := range keys { + delete(bc.items, key) } - if itm.isExpire() { - delete(bc.items, name) - return true - } - return false } func init() { From 2231841d74955b92993e034830e18543842d0751 Mon Sep 17 00:00:00 2001 From: miraclesu Date: Mon, 19 Jun 2017 18:10:09 +0800 Subject: [PATCH 12/38] validation: support int64 int32 int16 and int8 type --- validation/util.go | 20 +++++++++++++++ validation/validation.go | 6 ++--- validation/validation_test.go | 8 +++--- validation/validators.go | 46 ++++++++++++++++++++++++++--------- 4 files changed, 62 insertions(+), 18 deletions(-) diff --git a/validation/util.go b/validation/util.go index 9e7460a6..c8db0442 100644 --- a/validation/util.go +++ b/validation/util.go @@ -249,6 +249,26 @@ func parseParam(t reflect.Type, s string) (i interface{}, err error) { switch t.Kind() { case reflect.Int: i, err = strconv.Atoi(s) + case reflect.Int64: + i, err = strconv.ParseInt(s, 10, 64) + case reflect.Int32: + var v int64 + v, err = strconv.ParseInt(s, 10, 32) + if err == nil { + i = int32(v) + } + case reflect.Int16: + var v int64 + v, err = strconv.ParseInt(s, 10, 16) + if err == nil { + i = int16(v) + } + case reflect.Int8: + var v int64 + v, err = strconv.ParseInt(s, 10, 8) + if err == nil { + i = int8(v) + } case reflect.String: i = s case reflect.Ptr: diff --git a/validation/validation.go b/validation/validation.go index 9dc51106..9d05befc 100644 --- a/validation/validation.go +++ b/validation/validation.go @@ -144,17 +144,17 @@ func (v *Validation) Required(obj interface{}, key string) *Result { } // Min Test that the obj is greater than min if obj's type is int -func (v *Validation) Min(obj interface{}, min int, key string) *Result { +func (v *Validation) Min(obj interface{}, min int64, key string) *Result { return v.apply(Min{min, key}, obj) } // Max Test that the obj is less than max if obj's type is int -func (v *Validation) Max(obj interface{}, max int, key string) *Result { +func (v *Validation) Max(obj interface{}, max int64, key string) *Result { return v.apply(Max{max, key}, obj) } // Range Test that the obj is between mni and max if obj's type is int -func (v *Validation) Range(obj interface{}, min, max int, key string) *Result { +func (v *Validation) Range(obj interface{}, min, max int64, key string) *Result { return v.apply(Range{Min{Min: min}, Max{Max: max}, key}, obj) } diff --git a/validation/validation_test.go b/validation/validation_test.go index 71a8bd17..7a88acad 100644 --- a/validation/validation_test.go +++ b/validation/validation_test.go @@ -64,10 +64,10 @@ func TestRequired(t *testing.T) { func TestMin(t *testing.T) { valid := Validation{} - if valid.Min(-1, 0, "min0").Ok { + if valid.Min(int64(-1), int64(0), "min0").Ok { t.Error("-1 is less than the minimum value of 0 should be false") } - if !valid.Min(1, 0, "min0").Ok { + if !valid.Min(int64(1), int64(0), "min0").Ok { t.Error("1 is greater or equal than the minimum value of 0 should be true") } } @@ -75,10 +75,10 @@ func TestMin(t *testing.T) { func TestMax(t *testing.T) { valid := Validation{} - if valid.Max(1, 0, "max0").Ok { + if valid.Max(int64(1), int64(0), "max0").Ok { t.Error("1 is greater than the minimum value of 0 should be false") } - if !valid.Max(-1, 0, "max0").Ok { + if !valid.Max(int64(-1), int64(0), "max0").Ok { t.Error("-1 is less or equal than the maximum value of 0 should be true") } } diff --git a/validation/validators.go b/validation/validators.go index 5d489a55..264e61a1 100644 --- a/validation/validators.go +++ b/validation/validators.go @@ -161,17 +161,29 @@ func (r Required) GetLimitValue() interface{} { // Min check struct type Min struct { - Min int + Min int64 Key string } // IsSatisfied judge whether obj is valid func (m Min) IsSatisfied(obj interface{}) bool { - num, ok := obj.(int) - if ok { - return num >= m.Min + var v int64 + switch obj.(type) { + case int64: + v = obj.(int64) + case int: + v = int64(obj.(int)) + case int32: + v = int64(obj.(int32)) + case int16: + v = int64(obj.(int16)) + case int8: + v = int64(obj.(int8)) + default: + return false } - return false + + return v >= m.Min } // DefaultMessage return the default min error message @@ -191,17 +203,29 @@ func (m Min) GetLimitValue() interface{} { // Max validate struct type Max struct { - Max int + Max int64 Key string } // IsSatisfied judge whether obj is valid func (m Max) IsSatisfied(obj interface{}) bool { - num, ok := obj.(int) - if ok { - return num <= m.Max + var v int64 + switch obj.(type) { + case int64: + v = obj.(int64) + case int: + v = int64(obj.(int)) + case int32: + v = int64(obj.(int32)) + case int16: + v = int64(obj.(int16)) + case int8: + v = int64(obj.(int8)) + default: + return false } - return false + + return v <= m.Max } // DefaultMessage return the default max error message @@ -243,7 +267,7 @@ func (r Range) GetKey() string { // GetLimitValue return the limit value, Max func (r Range) GetLimitValue() interface{} { - return []int{r.Min.Min, r.Max.Max} + return []int64{r.Min.Min, r.Max.Max} } // MinSize Requires an array or string to be at least a given length. From 5a2eea07cb2cffc7178039b920b76923edb7a722 Mon Sep 17 00:00:00 2001 From: Jia Li Ong Date: Thu, 1 Jun 2017 17:48:48 +0800 Subject: [PATCH 13/38] Provide permission to access old log files to everyone --- logs/file.go | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/logs/file.go b/logs/file.go index 1c2db882..0b827857 100644 --- a/logs/file.go +++ b/logs/file.go @@ -56,17 +56,20 @@ type fileLogWriter struct { Perm string `json:"perm"` + OtherPerm string `json:"otherperm"` + fileNameOnly, suffix string // like "project.log", project is fileNameOnly and .log is suffix } // newFileWriter create a FileLogWriter returning as LoggerInterface. func newFileWriter() Logger { w := &fileLogWriter{ - Daily: true, - MaxDays: 7, - Rotate: true, - Level: LevelTrace, - Perm: "0660", + Daily: true, + MaxDays: 7, + Rotate: true, + OtherPerm: "0440", + Level: LevelTrace, + Perm: "0660", } return w } @@ -237,8 +240,12 @@ func (w *fileLogWriter) doRotate(logTime time.Time) error { // Find the next available number num := 1 fName := "" + otherPerm, err := strconv.ParseInt(w.OtherPerm, 8, 64) + if err != nil { + return err + } - _, err := os.Lstat(w.Filename) + _, err = os.Lstat(w.Filename) if err != nil { //even if the file is not exist or other ,we should RESTART the logger goto RESTART_LOGGER @@ -271,7 +278,9 @@ func (w *fileLogWriter) doRotate(logTime time.Time) error { if err != nil { goto RESTART_LOGGER } - err = os.Chmod(fName, os.FileMode(0440)) + //err = os.Chmod(fName, os.FileMode(0444)) + + err = os.Chmod(fName, os.FileMode(otherPerm)) // re-start logger RESTART_LOGGER: From 6e34f437218b7a9a47a4413e2cd79d3b072c486d Mon Sep 17 00:00:00 2001 From: miraclesu Date: Wed, 28 Jun 2017 16:56:37 +0800 Subject: [PATCH 14/38] Fix break API change support int64 on 64-bit platform --- validation/util.go | 11 ++++++++-- validation/validation.go | 6 +++--- validation/validation_test.go | 8 +++---- validation/validators.go | 39 +++++++++++++++++++++-------------- 4 files changed, 40 insertions(+), 24 deletions(-) diff --git a/validation/util.go b/validation/util.go index c8db0442..4695b776 100644 --- a/validation/util.go +++ b/validation/util.go @@ -25,6 +25,8 @@ import ( const ( // ValidTag struct tag ValidTag = "valid" + + wordsize = 32 << (^uint(0) >> 32 & 1) ) var ( @@ -43,6 +45,8 @@ var ( "Valid": true, "NoMatch": true, } + + Int64On32Err = fmt.Errorf("not support int64 on 32-bit platform") ) func init() { @@ -250,6 +254,9 @@ func parseParam(t reflect.Type, s string) (i interface{}, err error) { case reflect.Int: i, err = strconv.Atoi(s) case reflect.Int64: + if wordsize == 32 { + return nil, Int64On32Err + } i, err = strconv.ParseInt(s, 10, 64) case reflect.Int32: var v int64 @@ -273,12 +280,12 @@ func parseParam(t reflect.Type, s string) (i interface{}, err error) { i = s case reflect.Ptr: if t.Elem().String() != "regexp.Regexp" { - err = fmt.Errorf("does not support %s", t.Elem().String()) + err = fmt.Errorf("not support %s", t.Elem().String()) return } i, err = regexp.Compile(s) default: - err = fmt.Errorf("does not support %s", t.Kind().String()) + err = fmt.Errorf("not support %s", t.Kind().String()) } return } diff --git a/validation/validation.go b/validation/validation.go index 9d05befc..9dc51106 100644 --- a/validation/validation.go +++ b/validation/validation.go @@ -144,17 +144,17 @@ func (v *Validation) Required(obj interface{}, key string) *Result { } // Min Test that the obj is greater than min if obj's type is int -func (v *Validation) Min(obj interface{}, min int64, key string) *Result { +func (v *Validation) Min(obj interface{}, min int, key string) *Result { return v.apply(Min{min, key}, obj) } // Max Test that the obj is less than max if obj's type is int -func (v *Validation) Max(obj interface{}, max int64, key string) *Result { +func (v *Validation) Max(obj interface{}, max int, key string) *Result { return v.apply(Max{max, key}, obj) } // Range Test that the obj is between mni and max if obj's type is int -func (v *Validation) Range(obj interface{}, min, max int64, key string) *Result { +func (v *Validation) Range(obj interface{}, min, max int, key string) *Result { return v.apply(Range{Min{Min: min}, Max{Max: max}, key}, obj) } diff --git a/validation/validation_test.go b/validation/validation_test.go index 7a88acad..71a8bd17 100644 --- a/validation/validation_test.go +++ b/validation/validation_test.go @@ -64,10 +64,10 @@ func TestRequired(t *testing.T) { func TestMin(t *testing.T) { valid := Validation{} - if valid.Min(int64(-1), int64(0), "min0").Ok { + if valid.Min(-1, 0, "min0").Ok { t.Error("-1 is less than the minimum value of 0 should be false") } - if !valid.Min(int64(1), int64(0), "min0").Ok { + if !valid.Min(1, 0, "min0").Ok { t.Error("1 is greater or equal than the minimum value of 0 should be true") } } @@ -75,10 +75,10 @@ func TestMin(t *testing.T) { func TestMax(t *testing.T) { valid := Validation{} - if valid.Max(int64(1), int64(0), "max0").Ok { + if valid.Max(1, 0, "max0").Ok { t.Error("1 is greater than the minimum value of 0 should be false") } - if !valid.Max(int64(-1), int64(0), "max0").Ok { + if !valid.Max(-1, 0, "max0").Ok { t.Error("-1 is less or equal than the maximum value of 0 should be true") } } diff --git a/validation/validators.go b/validation/validators.go index 264e61a1..5248542a 100644 --- a/validation/validators.go +++ b/validation/validators.go @@ -161,24 +161,28 @@ func (r Required) GetLimitValue() interface{} { // Min check struct type Min struct { - Min int64 + Min int Key string } // IsSatisfied judge whether obj is valid +// not support int64 on 32-bit platform func (m Min) IsSatisfied(obj interface{}) bool { - var v int64 + var v int switch obj.(type) { case int64: - v = obj.(int64) + if wordsize == 32 { + return false + } + v = int(obj.(int64)) case int: - v = int64(obj.(int)) + v = obj.(int) case int32: - v = int64(obj.(int32)) + v = int(obj.(int32)) case int16: - v = int64(obj.(int16)) + v = int(obj.(int16)) case int8: - v = int64(obj.(int8)) + v = int(obj.(int8)) default: return false } @@ -203,24 +207,28 @@ func (m Min) GetLimitValue() interface{} { // Max validate struct type Max struct { - Max int64 + Max int Key string } // IsSatisfied judge whether obj is valid +// not support int64 on 32-bit platform func (m Max) IsSatisfied(obj interface{}) bool { - var v int64 + var v int switch obj.(type) { case int64: - v = obj.(int64) + if wordsize == 32 { + return false + } + v = int(obj.(int64)) case int: - v = int64(obj.(int)) + v = obj.(int) case int32: - v = int64(obj.(int32)) + v = int(obj.(int32)) case int16: - v = int64(obj.(int16)) + v = int(obj.(int16)) case int8: - v = int64(obj.(int8)) + v = int(obj.(int8)) default: return false } @@ -251,6 +259,7 @@ type Range struct { } // IsSatisfied judge whether obj is valid +// not support int64 on 32-bit platform func (r Range) IsSatisfied(obj interface{}) bool { return r.Min.IsSatisfied(obj) && r.Max.IsSatisfied(obj) } @@ -267,7 +276,7 @@ func (r Range) GetKey() string { // GetLimitValue return the limit value, Max func (r Range) GetLimitValue() interface{} { - return []int64{r.Min.Min, r.Max.Max} + return []int{r.Min.Min, r.Max.Max} } // MinSize Requires an array or string to be at least a given length. From 234708062a86ae0cb00002c2947443ffe800c550 Mon Sep 17 00:00:00 2001 From: xlwcom Date: Thu, 29 Jun 2017 13:32:40 +0800 Subject: [PATCH 15/38] fix the bug in the "ParseBool" function in the file of config.go --- config/config.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/config.go b/config/config.go index e8201a24..a9ef7a9a 100644 --- a/config/config.go +++ b/config/config.go @@ -189,16 +189,16 @@ func ParseBool(val interface{}) (value bool, err error) { return false, nil } case int8, int32, int64: - strV := fmt.Sprintf("%s", v) + strV := fmt.Sprintf("%d", v) // w 由 %s 修改为 %d if strV == "1" { return true, nil } else if strV == "0" { return false, nil } case float64: - if v == 1 { + if v == 1.0 { // w 由 1 修改为 1.0 return true, nil - } else if v == 0 { + } else if v == 0.0 { // w 由 0 修改为 0.0 return false, nil } } From e72b02b7cc99493af7286a8966ad3a8f0ed32496 Mon Sep 17 00:00:00 2001 From: miraclesu Date: Mon, 3 Jul 2017 16:14:29 +0800 Subject: [PATCH 16/38] validation: support required option for some struct tag valids --- validation/README.md | 3 +++ validation/validation.go | 17 ++++++++++++ validation/validation_test.go | 51 +++++++++++++++++++++++++++++++++++ validation/validators.go | 10 +++++++ 4 files changed, 81 insertions(+) diff --git a/validation/README.md b/validation/README.md index 5c3212b0..43373e47 100644 --- a/validation/README.md +++ b/validation/README.md @@ -64,6 +64,9 @@ Struct Tag Use: func main() { valid := validation.Validation{} + // ignore empty field valid + // see CanSkipFuncs + // valid := validation.Validation{RequiredFirst:true} u := user{Name: "test", Age: 40} b, err := valid.Valid(u) if err != nil { diff --git a/validation/validation.go b/validation/validation.go index 9dc51106..ef484fb3 100644 --- a/validation/validation.go +++ b/validation/validation.go @@ -106,6 +106,11 @@ func (r *Result) Message(message string, args ...interface{}) *Result { // A Validation context manages data validation and error messages. type Validation struct { + // if this field set true, in struct tag valid + // if the struct field vale is empty + // it will skip those valid functions, see CanSkipFuncs + RequiredFirst bool + Errors []*Error ErrorsMap map[string]*Error } @@ -324,7 +329,19 @@ func (v *Validation) Valid(obj interface{}) (b bool, err error) { if vfs, err = getValidFuncs(objT.Field(i)); err != nil { return } + + var hasReuired bool for _, vf := range vfs { + if vf.Name == "Required" { + hasReuired = true + } + + if !hasReuired && v.RequiredFirst && len(objV.Field(i).String()) == 0 { + if _, ok := CanSkipFuncs[vf.Name]; ok { + continue + } + } + if _, err = funcs.Call(vf.Name, mergeParam(v, objV.Field(i).Interface(), vf.Params)...); err != nil { return diff --git a/validation/validation_test.go b/validation/validation_test.go index 71a8bd17..bf612015 100644 --- a/validation/validation_test.go +++ b/validation/validation_test.go @@ -391,3 +391,54 @@ func TestRecursiveValid(t *testing.T) { t.Error("validation should not be passed") } } + +func TestSkipValid(t *testing.T) { + type User struct { + ID int + + Email string `valid:"Email"` + ReqEmail string `valid:"Required;Email"` + + IP string `valid:"IP"` + ReqIP string `valid:"Required;IP"` + + Mobile string `valid:"Mobile"` + ReqMobile string `valid:"Required;Mobile"` + + Tel string `valid:"Tel"` + ReqTel string `valid:"Required;Tel"` + + Phone string `valid:"Phone"` + ReqPhone string `valid:"Required;Phone"` + + ZipCode string `valid:"ZipCode"` + ReqZipCode string `valid:"Required;ZipCode"` + } + + u := User{ + ReqEmail: "a@a.com", + ReqIP: "127.0.0.1", + ReqMobile: "18888888888", + ReqTel: "02088888888", + ReqPhone: "02088888888", + ReqZipCode: "510000", + } + + valid := Validation{} + b, err := valid.Valid(u) + if err != nil { + t.Fatal(err) + } + if b { + t.Fatal("validation should not be passed") + } + + valid = Validation{RequiredFirst: true} + b, err = valid.Valid(u) + if err != nil { + t.Fatal(err) + } + if !b { + t.Fatal("validation should be passed") + } +} diff --git a/validation/validators.go b/validation/validators.go index 5248542a..a9c3e6b8 100644 --- a/validation/validators.go +++ b/validation/validators.go @@ -23,6 +23,16 @@ import ( "unicode/utf8" ) +// CanSkipFuncs will skip valid if RequiredFirst is true and the struct field's value is empty +var CanSkipFuncs = map[string]struct{}{ + "Email": struct{}{}, + "IP": struct{}{}, + "Mobile": struct{}{}, + "Tel": struct{}{}, + "Phone": struct{}{}, + "ZipCode": struct{}{}, +} + // MessageTmpls store commond validate template var MessageTmpls = map[string]string{ "Required": "Can not be empty", From 3c17e2a7e6e9b6e377359e70cb9e361e388ef0dc Mon Sep 17 00:00:00 2001 From: xlwcom Date: Tue, 4 Jul 2017 11:03:49 +0800 Subject: [PATCH 17/38] remove the comments --- config/config.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/config.go b/config/config.go index a9ef7a9a..c620504a 100644 --- a/config/config.go +++ b/config/config.go @@ -189,16 +189,16 @@ func ParseBool(val interface{}) (value bool, err error) { return false, nil } case int8, int32, int64: - strV := fmt.Sprintf("%d", v) // w 由 %s 修改为 %d + strV := fmt.Sprintf("%d", v) if strV == "1" { return true, nil } else if strV == "0" { return false, nil } case float64: - if v == 1.0 { // w 由 1 修改为 1.0 + if v == 1.0 { return true, nil - } else if v == 0.0 { // w 由 0 修改为 0.0 + } else if v == 0.0 { return false, nil } } From 7ec819deed1788d945d59ed1e400d1f2db0a2bf4 Mon Sep 17 00:00:00 2001 From: astaxie Date: Tue, 4 Jul 2017 21:16:59 +0800 Subject: [PATCH 18/38] fix #2725 big form --- context/input.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/context/input.go b/context/input.go index d9015ce3..aaf97e85 100644 --- a/context/input.go +++ b/context/input.go @@ -19,6 +19,7 @@ import ( "errors" "io" "io/ioutil" + "net/http" "net/url" "reflect" "regexp" @@ -353,7 +354,7 @@ func (input *BeegoInput) CopyBody(MaxMemory int64) []byte { requestbody, _ := ioutil.ReadAll(safe) input.Context.Request.Body.Close() bf := bytes.NewBuffer(requestbody) - input.Context.Request.Body = ioutil.NopCloser(bf) + input.Context.Request.Body = http.MaxBytesReader(input.Context.ResponseWriter, ioutil.NopCloser(bf), MaxMemory) input.RequestBody = requestbody return requestbody } From 6b9c3f48248ec2d85b9264c99ff9a27cc42d0489 Mon Sep 17 00:00:00 2001 From: Gnanakeethan Balasubramaniam Date: Thu, 6 Jul 2017 06:40:28 +0530 Subject: [PATCH 19/38] [Proposal] Database Migrations; Summary: The database migrations now can be created using the methods on the migration struct. it does not break any existing migration features. it upgrades the migration struct and adds few more struct types so that the migrations can be efficiently generated for create, alter, reverse, drop. Current Features: * Supports creation of columns * `m.NewCol("name").SetDataType("VARCHAR(10)").SetNullable("true")` * **NOTE** `SetNullable` & `SetDefault` methods should not be called on same column for consistency * Supports addition of primary keys * `m.PriCol("id").SetDataType("INT(10)").SetNullable("true")` * **NOTE** `setAuto(true)` can be only called on Primary keys * Supports addition of unique keys * `m.UniCol("unique_index","column_name").SetDataType("VARCHAR(23)").SetNullable("true")` * **NOTE** `UniCol` can be called again with the same index name to add column to the index * Supports rename of columns * `m.RenameColumn("from_name","to_name")` * Allows standard column methods and methods such that, `SetOldDefault` allows reversibility of renames * TODO: * ForeignKey Signed-off-by: Gnanakeethan Balasubramaniam --- migration/ddl.go | 333 ++++++++++++++++++++++++++++++++++++++--- migration/migration.go | 30 +++- 2 files changed, 333 insertions(+), 30 deletions(-) diff --git a/migration/ddl.go b/migration/ddl.go index 51243337..4389ca8c 100644 --- a/migration/ddl.go +++ b/migration/ddl.go @@ -12,42 +12,327 @@ // See the License for the specific language governing permissions and // limitations under the License. -package migration +package m -// Table store the tablename and Column -type Table struct { - TableName string - Columns []*Column +import ( + "fmt" + + "github.com/astaxie/beego" +) + +// Index struct defines the structure of Index Columns +type Index struct { + Name string } -// Create return the create sql -func (t *Table) Create() string { - return "" +// Foreign struct defines a single foreign relationship +type Foreign struct { + Column *Column + ForeignTable string + ForeignColumn string } -// Drop return the drop sql -func (t *Table) Drop() string { - return "" +// Unique struct defines a single unique key combination +type Unique struct { + Definition string + Columns []*Column } -// Column define the columns name type and Default +//Column struct defines a single column of a table type Column struct { - Name string - Type string - Default interface{} + Name string + Inc string + Null string + Default string + Unsign string + DataType string + remove bool + Modify bool } -// Create return create sql with the provided tbname and columns -func Create(tbname string, columns ...Column) string { - return "" +// RenameColumn struct allows renaming of columns +type RenameColumn struct { + OldName string + OldNull string + OldDefault string + OldUnsign string + OldDataType string + NewName string + Column } -// Drop return the drop sql with the provided tbname and columns -func Drop(tbname string, columns ...Column) string { - return "" +// NewCol creates a new standard column and attaches it to m struct +func (m *Migration) NewCol(name string) *Column { + col := &Column{Name: name} + m.AddColumns(col) + return col } -// TableDDL is still in think -func TableDDL(tbname string, columns ...Column) string { - return "" +//PriCol creates a new primary column and attaches it to m struct +func (m *Migration) PriCol(name string) *Column { + col := &Column{Name: name} + m.AddColumns(col) + m.AddPrimary(col) + return col +} + +//UniCol creates / appends columns to specified unique key and attaches it to m struct +func (m *Migration) UniCol(uni, name string) *Column { + col := &Column{Name: name} + m.AddColumns(col) + + uniqueOriginal := &Unique{} + + for _, unique := range m.Uniques { + if unique.Definition == uni { + unique.AddColumnsToUnique(col) + uniqueOriginal = unique + } + } + if uniqueOriginal.Definition == "" { + unique := &Unique{Definition: uni} + unique.AddColumnsToUnique(col) + m.AddUnique(unique) + } + + return col +} + +//Remove marks the columns to be removed. +//it allows reverse m to create the column. +func (c *Column) Remove() { + c.remove = true +} + +//SetAuto enables auto_increment of column (can be used once) +func (c *Column) SetAuto(inc bool) *Column { + if inc { + c.Inc = "auto_increment" + } + return c +} + +//SetNullable sets the column to be null +func (c *Column) SetNullable(null bool) *Column { + if null { + c.Null = "DEFAULT NULL" + + } else { + c.Null = "NOT NULL" + } + return c +} + +//SetDefault sets the default value, prepend with "DEFAULT " +func (c *Column) SetDefault(def string) *Column { + c.Default = def + return c +} + +//SetUnsigned sets the column to be unsigned int +func (c *Column) SetUnsigned(unsign bool) *Column { + if unsign { + c.Unsign = "UNSIGNED" + } + return c +} + +//SetDataType sets the dataType of the column +func (c *Column) SetDataType(dataType string) *Column { + c.DataType = dataType + return c +} + +//SetOldNullable allows reverting to previous nullable on reverse ms +func (c *RenameColumn) SetOldNullable(null bool) *RenameColumn { + if null { + c.OldNull = "DEFAULT NULL" + + } else { + c.OldNull = "NOT NULL" + } + return c +} + +//SetOldDefault allows reverting to previous default on reverse ms +func (c *RenameColumn) SetOldDefault(def string) *RenameColumn { + c.OldDefault = def + return c +} + +//SetOldUnsigned allows reverting to previous unsgined on reverse ms +func (c *RenameColumn) SetOldUnsigned(unsign bool) *RenameColumn { + if unsign { + c.OldUnsign = "UNSIGNED" + } + return c +} + +//SetOldDataType allows reverting to previous datatype on reverse ms +func (c *RenameColumn) SetOldDataType(dataType string) *RenameColumn { + c.OldDataType = dataType + return c +} + +//SetPrimary adds the columns to the primary key (can only be used any number of times in only one m) +func (c *Column) SetPrimary(m *Migration) *Column { + m.Primary = append(m.Primary, c) + return c +} + +//AddColumnsToUnique adds the columns to Unique Struct +func (unique *Unique) AddColumnsToUnique(columns ...*Column) *Unique { + + unique.Columns = append(unique.Columns, column...) + + return unique +} + +//AddColumns adds columns to m struct +func (m *Migration) AddColumns(columns ...*Column) *Migration { + + m.Columns = append(m.Columns, column...) + + return m +} + +//AddPrimary adds the column to primary in m struct +func (m *Migration) AddPrimary(primary *Column) *Migration { + m.Primary = append(m.Primary, primary) + return m +} + +//AddUnique adds the column to unique in m struct +func (m *Migration) AddUnique(unique *Unique) *Migration { + m.Uniques = append(m.Uniques, unique) + return m +} + +//AddForeign adds the column to foreign in m struct +func (m *Migration) AddForeign(foreign *Foreign) *Migration { + m.Foreigns = append(m.Foreigns, foreign) + return m +} + +//AddIndex adds the column to index in m struct +func (m *Migration) AddIndex(index *Index) *Migration { + m.Indexes = append(m.Indexes, index) + return m +} + +//RenameColumn allows renaming of columns +func (m *Migration) RenameColumn(from, to string) *RenameColumn { + rename := &RenameColumn{OldName: from, NewName: to} + m.Renames = append(m.Renames, rename) + return rename +} + +//GetSQL returns the generated sql depending on ModifyType +func (m *Migration) GetSQL() (sql string) { + sql = "" + switch m.ModifyType { + case "create": + { + sql += fmt.Sprintf("CREATE TABLE `%s` (", m.TableName) + for index, column := range m.Columns { + sql += fmt.Sprintf("\n `%s` %s %s %s %s %s", column.Name, column.DataType, column.Unsign, column.Null, column.Inc, column.Default) + if len(m.Columns) > index+1 { + sql += "," + } + } + + if len(m.Primary) > 0 { + sql += fmt.Sprintf(",\n PRIMARY KEY( ") + } + for index, column := range m.Primary { + sql += fmt.Sprintf(" `%s`", column.Name) + if len(m.Primary) > index+1 { + sql += "," + } + + } + if len(m.Primary) > 0 { + sql += fmt.Sprintf(")") + } + + for _, unique := range m.Uniques { + sql += fmt.Sprintf(",\n UNIQUE KEY `%s`( ", unique.Definition) + for index, column := range unique.Columns { + sql += fmt.Sprintf(" `%s`", column.Name) + if len(unique.Columns) > index+1 { + sql += "," + } + } + sql += fmt.Sprintf(")") + } + sql += fmt.Sprintf(")ENGINE=%s DEFAULT CHARSET=%s;", m.Engine, m.Charset) + break + } + case "alter": + { + sql += fmt.Sprintf("ALTER TABLE `%s` ", m.TableName) + for index, column := range m.Columns { + if !column.remove { + beego.BeeLogger.Info("col") + sql += fmt.Sprintf("\n ADD `%s` %s %s %s %s %s", column.Name, column.DataType, column.Unsign, column.Null, column.Inc, column.Default) + } else { + sql += fmt.Sprintf("\n DROP COLUMN `%s`", column.Name) + } + + if len(m.Columns) > index+1 { + sql += "," + } + } + for index, column := range m.Renames { + sql += fmt.Sprintf(",\n CHANGE COLUMN `%s` `%s` %s %s %s %s %s", column.OldName, column.NewName, column.DataType, column.Unsign, column.Null, column.Inc, column.Default) + if len(m.Renames) > index+1 { + sql += "," + } + } + + sql += ";" + + break + } + case "reverse": + { + + sql += fmt.Sprintf("ALTER TABLE `%s`", m.TableName) + for index, column := range m.Columns { + if column.remove { + sql += fmt.Sprintf("\n ADD `%s` %s %s %s %s %s", column.Name, column.DataType, column.Unsign, column.Null, column.Inc, column.Default) + } else { + sql += fmt.Sprintf("\n DROP COLUMN `%s`", column.Name) + } + if len(m.Columns) > index+1 { + sql += "," + } + } + + if len(m.Primary) > 0 { + sql += fmt.Sprintf(",\n DROP PRIMARY KEY") + } + + for index, unique := range m.Uniques { + sql += fmt.Sprintf(",\n DROP KEY `%s`", unique.Definition) + if len(m.Uniques) > index+1 { + sql += "," + } + + } + for index, column := range m.Renames { + sql += fmt.Sprintf(",\n CHANGE COLUMN `%s` `%s` %s %s %s %s", column.NewName, column.OldName, column.OldDataType, column.OldUnsign, column.OldNull, column.OldDefault) + if len(m.Renames) > index+1 { + sql += "," + } + } + sql += ";" + } + case "delete": + { + sql += fmt.Sprintf("DROP TABLE IF EXISTS `%s`;", m.TableName) + } + } + + return } diff --git a/migration/migration.go b/migration/migration.go index c9ca1bc6..2bfa8bd4 100644 --- a/migration/migration.go +++ b/migration/migration.go @@ -52,6 +52,25 @@ type Migrationer interface { GetCreated() int64 } +type Migration struct { + sqls []string + Created string + TableName string + Engine string + Charset string + ModifyType string + Columns []*Column + Indexes []*Index + Primary []*Column + Uniques []*Unique + Foreigns []*Foreign + Renames []*RenameColumn + RemoveColumns []*Column + RemoveIndexes []*Index + RemoveUniques []*Unique + RemoveForeigns []*Foreign +} + var ( migrationMap map[string]Migrationer ) @@ -60,12 +79,6 @@ func init() { migrationMap = make(map[string]Migrationer) } -// Migration the basic type which will implement the basic type -type Migration struct { - sqls []string - Created string -} - // Up implement in the Inheritance struct for upgrade func (m *Migration) Up() { @@ -76,6 +89,11 @@ func (m *Migration) Down() { } +func (m *Migration) Migrate(migrationType string) { + m.ModifyType = migrationType + m.sqls = append(m.sqls, m.GetSQL()) +} + // SQL add sql want to execute func (m *Migration) SQL(sql string) { m.sqls = append(m.sqls, sql) From ed558a0e709a0e7b3db45ecc79055b90fd307ad5 Mon Sep 17 00:00:00 2001 From: Gnanakeethan Balasubramaniam Date: Thu, 6 Jul 2017 07:45:07 +0530 Subject: [PATCH 20/38] Fix: typo due to find and replace migration renamed to m Signed-off-by: Gnanakeethan Balasubramaniam --- migration/ddl.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migration/ddl.go b/migration/ddl.go index 4389ca8c..f1f19783 100644 --- a/migration/ddl.go +++ b/migration/ddl.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package m +package migration import ( "fmt" From c1ba11f53125e5d3480ed590c1748c6e24e9763e Mon Sep 17 00:00:00 2001 From: Gnanakeethan Balasubramaniam Date: Thu, 6 Jul 2017 14:58:40 +0530 Subject: [PATCH 21/38] Fixing typo Signed-off-by: Gnanakeethan Balasubramaniam --- migration/ddl.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/migration/ddl.go b/migration/ddl.go index f1f19783..0702b020 100644 --- a/migration/ddl.go +++ b/migration/ddl.go @@ -183,7 +183,7 @@ func (c *Column) SetPrimary(m *Migration) *Column { //AddColumnsToUnique adds the columns to Unique Struct func (unique *Unique) AddColumnsToUnique(columns ...*Column) *Unique { - unique.Columns = append(unique.Columns, column...) + unique.Columns = append(unique.Columns, columns...) return unique } @@ -191,7 +191,7 @@ func (unique *Unique) AddColumnsToUnique(columns ...*Column) *Unique { //AddColumns adds columns to m struct func (m *Migration) AddColumns(columns ...*Column) *Migration { - m.Columns = append(m.Columns, column...) + m.Columns = append(m.Columns, columns...) return m } From e888fee4e07883b0c50b5c95261a56857707f7e7 Mon Sep 17 00:00:00 2001 From: Gnanakeethan Balasubramaniam Date: Thu, 6 Jul 2017 20:26:37 +0530 Subject: [PATCH 22/38] Update: Foreign Key & Comments Summary: Foreign Key functions are now available Signed-off-by: Gnanakeethan Balasubramaniam --- migration/ddl.go | 78 +++++++++++++++++++++++++++++++++--------- migration/migration.go | 1 + 2 files changed, 63 insertions(+), 16 deletions(-) diff --git a/migration/ddl.go b/migration/ddl.go index 0702b020..3b405498 100644 --- a/migration/ddl.go +++ b/migration/ddl.go @@ -25,13 +25,6 @@ type Index struct { Name string } -// Foreign struct defines a single foreign relationship -type Foreign struct { - Column *Column - ForeignTable string - ForeignColumn string -} - // Unique struct defines a single unique key combination type Unique struct { Definition string @@ -50,6 +43,15 @@ type Column struct { Modify bool } +// Foreign struct defines a single foreign relationship +type Foreign struct { + ForeignTable string + ForeignColumn string + OnDelete string + OnUpdate string + Column +} + // RenameColumn struct allows renaming of columns type RenameColumn struct { OldName string @@ -98,6 +100,27 @@ func (m *Migration) UniCol(uni, name string) *Column { return col } +//ForeignCol creates a new foreign column and returns the instance of column +func (m *Migration) ForeignCol(colname, foreigncol, foreigntable string) (foreign *Foreign) { + + foreign = &Foreign{ForeignColumn: foreigncol, ForeignTable: foreigntable} + foreign.Name = colname + m.AddForeign(foreign) + return foreign +} + +//SetOnDelete sets the on delete of foreign +func (foreign *Foreign) SetOnDelete(del string) *Foreign { + foreign.OnDelete = "ON DELETE" + del + return foreign +} + +//SetOnUpdate sets the on update of foreign +func (foreign *Foreign) SetOnUpdate(update string) *Foreign { + foreign.OnUpdate = "ON UPDATE" + update + return foreign +} + //Remove marks the columns to be removed. //it allows reverse m to create the column. func (c *Column) Remove() { @@ -125,7 +148,7 @@ func (c *Column) SetNullable(null bool) *Column { //SetDefault sets the default value, prepend with "DEFAULT " func (c *Column) SetDefault(def string) *Column { - c.Default = def + c.Default = "DEFAULT " + def return c } @@ -265,6 +288,15 @@ func (m *Migration) GetSQL() (sql string) { } sql += fmt.Sprintf(")") } + for index, foreign := range m.Foreigns { + sql += fmt.Sprintf(",\n `%s` %s %s %s %s %s", foreign.Name, foreign.DataType, foreign.Unsign, foreign.Null, foreign.Inc, foreign.Default) + sql += fmt.Sprintf(",\n KEY `%s_%s_foreign`(`%s`),", m.TableName, foreign.Column.Name, foreign.Column.Name) + sql += fmt.Sprintf("\n CONSTRAINT `%s_%s_foreign` FOREIGN KEY (`%s`) REFERENCES `%s` (`%s`) %s %s", m.TableName, foreign.Column.Name, foreign.Column.Name, foreign.ForeignTable, foreign.ForeignColumn, foreign.OnDelete, foreign.OnUpdate) + + if len(m.Foreigns) > index+1 { + sql += "," + } + } sql += fmt.Sprintf(")ENGINE=%s DEFAULT CHARSET=%s;", m.Engine, m.Charset) break } @@ -279,17 +311,25 @@ func (m *Migration) GetSQL() (sql string) { sql += fmt.Sprintf("\n DROP COLUMN `%s`", column.Name) } - if len(m.Columns) > index+1 { + if len(m.Columns) > index { sql += "," } } for index, column := range m.Renames { - sql += fmt.Sprintf(",\n CHANGE COLUMN `%s` `%s` %s %s %s %s %s", column.OldName, column.NewName, column.DataType, column.Unsign, column.Null, column.Inc, column.Default) + sql += fmt.Sprintf("CHANGE COLUMN `%s` `%s` %s %s %s %s %s", column.OldName, column.NewName, column.DataType, column.Unsign, column.Null, column.Inc, column.Default) if len(m.Renames) > index+1 { sql += "," } } + for index, foreign := range m.Foreigns { + sql += fmt.Sprintf("ADD `%s` %s %s %s %s %s", foreign.Name, foreign.DataType, foreign.Unsign, foreign.Null, foreign.Inc, foreign.Default) + sql += fmt.Sprintf(",\n ADD KEY `%s_%s_foreign`(`%s`)", m.TableName, foreign.Column.Name, foreign.Column.Name) + sql += fmt.Sprintf(",\n ADD CONSTRAINT `%s_%s_foreign` FOREIGN KEY (`%s`) REFERENCES `%s` (`%s`) %s %s", m.TableName, foreign.Column.Name, foreign.Column.Name, foreign.ForeignTable, foreign.ForeignColumn, foreign.OnDelete, foreign.OnUpdate) + if len(m.Foreigns) > index+1 { + sql += "," + } + } sql += ";" break @@ -304,28 +344,34 @@ func (m *Migration) GetSQL() (sql string) { } else { sql += fmt.Sprintf("\n DROP COLUMN `%s`", column.Name) } - if len(m.Columns) > index+1 { + if len(m.Columns) > index { sql += "," } } if len(m.Primary) > 0 { - sql += fmt.Sprintf(",\n DROP PRIMARY KEY") + sql += fmt.Sprintf("\n DROP PRIMARY KEY,") } for index, unique := range m.Uniques { - sql += fmt.Sprintf(",\n DROP KEY `%s`", unique.Definition) - if len(m.Uniques) > index+1 { + sql += fmt.Sprintf("\n DROP KEY `%s`", unique.Definition) + if len(m.Uniques) > index { sql += "," } } for index, column := range m.Renames { - sql += fmt.Sprintf(",\n CHANGE COLUMN `%s` `%s` %s %s %s %s", column.NewName, column.OldName, column.OldDataType, column.OldUnsign, column.OldNull, column.OldDefault) - if len(m.Renames) > index+1 { + sql += fmt.Sprintf("\n CHANGE COLUMN `%s` `%s` %s %s %s %s", column.NewName, column.OldName, column.OldDataType, column.OldUnsign, column.OldNull, column.OldDefault) + if len(m.Renames) > index { sql += "," } } + + for _, foreign := range m.Foreigns { + sql += fmt.Sprintf("\n DROP KEY `%s_%s_foreign`", m.TableName, foreign.Column.Name) + sql += fmt.Sprintf(",\n DROP FOREIGN KEY `%s_%s_foreign`", m.TableName, foreign.Column.Name) + sql += fmt.Sprintf(",\n DROP COLUMN `%s`", foreign.Name) + } sql += ";" } case "delete": diff --git a/migration/migration.go b/migration/migration.go index 2bfa8bd4..d1387ba0 100644 --- a/migration/migration.go +++ b/migration/migration.go @@ -89,6 +89,7 @@ func (m *Migration) Down() { } +//Migrate adds the SQL to the execution list func (m *Migration) Migrate(migrationType string) { m.ModifyType = migrationType m.sqls = append(m.sqls, m.GetSQL()) From 83a563c0abdbbd8f74dbf807d4321a1e47bf91f0 Mon Sep 17 00:00:00 2001 From: satng Date: Sun, 9 Jul 2017 12:25:51 +0800 Subject: [PATCH 23/38] =?UTF-8?q?oracle=E6=8F=92=E5=85=A5=E5=8D=A0?= =?UTF-8?q?=E4=BD=8D=E7=AC=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- orm/db_oracle.go | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/orm/db_oracle.go b/orm/db_oracle.go index deca36ad..f5d6aaa2 100644 --- a/orm/db_oracle.go +++ b/orm/db_oracle.go @@ -94,3 +94,43 @@ func (d *dbBaseOracle) IndexExists(db dbQuerier, table string, name string) bool row.Scan(&cnt) return cnt > 0 } + +// execute insert sql with given struct and given values. +// insert the given values, not the field values in struct. +func (d *dbBaseOracle) InsertValue(q dbQuerier, mi *modelInfo, isMulti bool, names []string, values []interface{}) (int64, error) { + Q := d.ins.TableQuote() + + marks := make([]string, len(names)) + for i := range marks { + marks[i] = ":" + names[i] + } + + sep := fmt.Sprintf("%s, %s", Q, Q) + qmarks := strings.Join(marks, ", ") + columns := strings.Join(names, sep) + + multi := len(values) / len(names) + + if isMulti { + qmarks = strings.Repeat(qmarks+"), (", multi-1) + qmarks + } + + query := fmt.Sprintf("INSERT INTO %s%s%s (%s%s%s) VALUES (%s)", Q, mi.table, Q, Q, columns, Q, qmarks) + + d.ins.ReplaceMarks(&query) + + if isMulti || !d.ins.HasReturningID(mi, &query) { + res, err := q.Exec(query, values...) + if err == nil { + if isMulti { + return res.RowsAffected() + } + return res.LastInsertId() + } + return 0, err + } + row := q.QueryRow(query, values...) + var id int64 + err := row.Scan(&id) + return id, err +} From 29bcd31b27c822043b9d1b42f348483975061cd9 Mon Sep 17 00:00:00 2001 From: MiskoLee Date: Mon, 10 Jul 2017 21:27:54 +0800 Subject: [PATCH 24/38] supported gzip for req.Header has `Content-Encoding: gzip` --- context/input.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/context/input.go b/context/input.go index aaf97e85..2c53c601 100644 --- a/context/input.go +++ b/context/input.go @@ -16,6 +16,7 @@ package context import ( "bytes" + "compress/gzip" "errors" "io" "io/ioutil" @@ -350,8 +351,19 @@ func (input *BeegoInput) CopyBody(MaxMemory int64) []byte { if input.Context.Request.Body == nil { return []byte{} } + + var requestbody []byte safe := &io.LimitedReader{R: input.Context.Request.Body, N: MaxMemory} - requestbody, _ := ioutil.ReadAll(safe) + if input.Header("Content-Encoding") == "gzip" { + reader, err := gzip.NewReader(safe) + if err != nil { + return nil + } + requestbody, _ = ioutil.ReadAll(reader) + } else { + requestbody, _ = ioutil.ReadAll(safe) + } + input.Context.Request.Body.Close() bf := bytes.NewBuffer(requestbody) input.Context.Request.Body = http.MaxBytesReader(input.Context.ResponseWriter, ioutil.NopCloser(bf), MaxMemory) From c903de41e404aad3ee5501d2af0c4ce36a0bcee9 Mon Sep 17 00:00:00 2001 From: Gerson Alexander Pardo Gamez Date: Wed, 12 Jul 2017 09:51:37 -0500 Subject: [PATCH 25/38] updated sample for FilterMonitorFunc added pattern to sample --- admin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin.go b/admin.go index e6f9c3f9..0688dcbc 100644 --- a/admin.go +++ b/admin.go @@ -37,7 +37,7 @@ var beeAdminApp *adminApp // FilterMonitorFunc is default monitor filter when admin module is enable. // if this func returns, admin module records qbs for this request by condition of this function logic. // usage: -// func MyFilterMonitor(method, requestPath string, t time.Duration, statusCode int) bool { +// func MyFilterMonitor(method, requestPath string, t time.Duration, pattern string, statusCode int) bool { // if method == "POST" { // return false // } From 7c2ec075a4fb45ca4dd25e7ae7585417d9c99b53 Mon Sep 17 00:00:00 2001 From: Gnanakeethan Balasubramaniam Date: Thu, 13 Jul 2017 21:03:30 +0530 Subject: [PATCH 26/38] Update: fixing some methods and adding documentation Signed-off-by: Gnanakeethan Balasubramaniam --- migration/ddl.go | 13 ++++++++++++ migration/doc.go | 48 ++++++++++++++++++++++++++++++++++++++++++ migration/migration.go | 16 +++++++++++++- 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 migration/doc.go diff --git a/migration/ddl.go b/migration/ddl.go index 3b405498..9d4bfc11 100644 --- a/migration/ddl.go +++ b/migration/ddl.go @@ -63,6 +63,19 @@ type RenameColumn struct { Column } +// CreateTable creates the table on system +func (m *Migration) CreateTable(tablename, engine, charset string, p ...func()) { + m.TableName = tablename + m.Engine = engine + m.Charset = charset + m.ModifyType = "create" +} + +func (m *Migration) AlterTable(tablename string) { + m.TableName = tablename + m.ModifyType = "alter" +} + // NewCol creates a new standard column and attaches it to m struct func (m *Migration) NewCol(name string) *Column { col := &Column{Name: name} diff --git a/migration/doc.go b/migration/doc.go new file mode 100644 index 00000000..51050ed2 --- /dev/null +++ b/migration/doc.go @@ -0,0 +1,48 @@ +package migration + +/* Package migration enables you to generate migrations back and forth. It generates both migrations. + + +//Creates a table +m.CreateTable("tablename","InnoDB","utf8"); + + + +//Alter a table +m.AlterTable("tablename") + + + +//Standard Column Methods +* SetDataType +* SetNullable +* SetDefault +* SetUnsigned (use only on integer types unless produces error) + + +//Sets a primary column, multiple calls allowed, standard column methods available +m.PriCol("id").SetAuto(true).SetNullable(false).SetDataType("INT(10)").SetUnsigned(true) + +//UniCol Can be used multiple times, allows standard Column methods. Use same "index" string to add to same index +m.UniCol("index","column") + +//Standard Column Initialisation, can call .Remove() after NewCol("") on alter to remove +m.NewCol("name").SetDataType("VARCHAR(255) COLLATE utf8_unicode_ci").SetNullable(false) +m.NewCol("value").SetDataType("DOUBLE(8,2)").SetNullable(false) + +//Rename Columns , only use with Alter table, doesn't works with Create, prefix standard column methods with "Old" to +//create a true reversible migration eg: SetOldDataType("DOUBLE(12,3)") +m.RenameColumn("from","to")... + + +//Foreign Columns, single columns are only supported, SetOnDelete & SetOnUpdate are available, call appropriately. +//Supports standard column methods, automatic reverse. +m.ForeignCol("local_col","foreign_col","foreign_table") + + + + + + + +*/ diff --git a/migration/migration.go b/migration/migration.go index d1387ba0..ef42c986 100644 --- a/migration/migration.go +++ b/migration/migration.go @@ -52,6 +52,7 @@ type Migrationer interface { GetCreated() int64 } +//Migration defines the migrations by either SQL or DDL type Migration struct { sqls []string Created string @@ -82,11 +83,24 @@ func init() { // Up implement in the Inheritance struct for upgrade func (m *Migration) Up() { + switch m.ModifyType { + case "reverse": + m.ModifyType = "alter" + case "delete": + m.ModifyType = "create" + } + m.sqls = append(m.sqls, m.GetSQL()) } // Down implement in the Inheritance struct for down func (m *Migration) Down() { - + switch m.ModifyType { + case "alter": + m.ModifyType = "reverse" + case "create": + m.ModifyType = "delete" + } + m.sqls = append(m.sqls, m.GetSQL()) } //Migrate adds the SQL to the execution list From d453242e4870c06e60baa19ded97470a4d25ef63 Mon Sep 17 00:00:00 2001 From: Gnanakeethan Balasubramaniam Date: Fri, 14 Jul 2017 14:42:56 +0530 Subject: [PATCH 27/38] Update: moving package to bottom Signed-off-by: Gnanakeethan Balasubramaniam --- migration/doc.go | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/migration/doc.go b/migration/doc.go index 51050ed2..2d6ccaf6 100644 --- a/migration/doc.go +++ b/migration/doc.go @@ -1,5 +1,3 @@ -package migration - /* Package migration enables you to generate migrations back and forth. It generates both migrations. @@ -39,10 +37,5 @@ m.RenameColumn("from","to")... //Supports standard column methods, automatic reverse. m.ForeignCol("local_col","foreign_col","foreign_table") - - - - - - */ +package migration From fc86f6422d613b5811b6b07779f506f1eea960da Mon Sep 17 00:00:00 2001 From: "shanfeng.yang" Date: Sat, 15 Jul 2017 17:26:20 +0800 Subject: [PATCH 28/38] sort ControllerComments --- controller.go | 6 ++++++ parser.go | 1 + 2 files changed, 7 insertions(+) diff --git a/controller.go b/controller.go index 510e16b8..da8e8504 100644 --- a/controller.go +++ b/controller.go @@ -55,6 +55,12 @@ type ControllerComments struct { MethodParams []*param.MethodParam } +type ControllerCommentsSlice []ControllerComments + +func (p ControllerCommentsSlice) Len() int { return len(p) } +func (p ControllerCommentsSlice) Less(i, j int) bool { return p[i].Router < p[j].Router } +func (p ControllerCommentsSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } + // Controller defines some basic http request handler operations, such as // http context, template and view, session and xsrf. type Controller struct { diff --git a/parser.go b/parser.go index a9cfd894..f9357b99 100644 --- a/parser.go +++ b/parser.go @@ -274,6 +274,7 @@ func genRouterCode(pkgRealpath string) { sort.Strings(sortKey) for _, k := range sortKey { cList := genInfoList[k] + sort.Sort(ControllerCommentsSlice(cList)) for _, c := range cList { allmethod := "nil" if len(c.AllowHTTPMethods) > 0 { From cb38ab4f85bff7c368ea0b85036d14aa9eebf1da Mon Sep 17 00:00:00 2001 From: Gnanakeethan Balasubramaniam Date: Sun, 16 Jul 2017 07:10:09 +0530 Subject: [PATCH 29/38] Update: fixing a SQL generation code Signed-off-by: Gnanakeethan Balasubramaniam --- migration/ddl.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/migration/ddl.go b/migration/ddl.go index 9d4bfc11..d7d08f9e 100644 --- a/migration/ddl.go +++ b/migration/ddl.go @@ -151,7 +151,7 @@ func (c *Column) SetAuto(inc bool) *Column { //SetNullable sets the column to be null func (c *Column) SetNullable(null bool) *Column { if null { - c.Null = "DEFAULT NULL" + c.Null = "" } else { c.Null = "NOT NULL" @@ -182,7 +182,7 @@ func (c *Column) SetDataType(dataType string) *Column { //SetOldNullable allows reverting to previous nullable on reverse ms func (c *RenameColumn) SetOldNullable(null bool) *RenameColumn { if null { - c.OldNull = "DEFAULT NULL" + c.OldNull = "" } else { c.OldNull = "NOT NULL" From d58ad2ee3697ff0ccda83d020abc7080d99f0a5e Mon Sep 17 00:00:00 2001 From: Gnanakeethan Balasubramaniam Date: Sun, 16 Jul 2017 07:24:58 +0530 Subject: [PATCH 30/38] Update: removing the need to call DDLSpec in the migration file Signed-off-by: Gnanakeethan Balasubramaniam --- migration/migration.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/migration/migration.go b/migration/migration.go index ef42c986..e538eff9 100644 --- a/migration/migration.go +++ b/migration/migration.go @@ -80,9 +80,14 @@ func init() { migrationMap = make(map[string]Migrationer) } +//DDLSpec implement in the Inheritance struct for defining structure +func (m *Migration) DDLSpec() { + +} + // Up implement in the Inheritance struct for upgrade func (m *Migration) Up() { - + m.DDLSpec() switch m.ModifyType { case "reverse": m.ModifyType = "alter" From fc55c2b57cc464c2a1e4db2dedcefd65e094f66a Mon Sep 17 00:00:00 2001 From: Gnanakeethan Balasubramaniam Date: Sun, 16 Jul 2017 07:30:53 +0530 Subject: [PATCH 31/38] Update: missed to call DDLSpec in Down migration Signed-off-by: Gnanakeethan Balasubramaniam --- migration/migration.go | 1 + 1 file changed, 1 insertion(+) diff --git a/migration/migration.go b/migration/migration.go index e538eff9..c5a9352e 100644 --- a/migration/migration.go +++ b/migration/migration.go @@ -99,6 +99,7 @@ func (m *Migration) Up() { // Down implement in the Inheritance struct for down func (m *Migration) Down() { + m.DDLSpec() switch m.ModifyType { case "alter": m.ModifyType = "reverse" From 749a4028b48c87da63c95e7a3b4d57618e82645d Mon Sep 17 00:00:00 2001 From: Gnanakeethan Balasubramaniam Date: Sun, 16 Jul 2017 08:11:10 +0530 Subject: [PATCH 32/38] Revert "Update: removing the need to call DDLSpec in the migration file" The odds of getting this perfectly up is not good. This reverts commit d58ad2ee3697ff0ccda83d020abc7080d99f0a5e. --- migration/migration.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/migration/migration.go b/migration/migration.go index c5a9352e..0a140b24 100644 --- a/migration/migration.go +++ b/migration/migration.go @@ -80,14 +80,9 @@ func init() { migrationMap = make(map[string]Migrationer) } -//DDLSpec implement in the Inheritance struct for defining structure -func (m *Migration) DDLSpec() { - -} - // Up implement in the Inheritance struct for upgrade func (m *Migration) Up() { - m.DDLSpec() + switch m.ModifyType { case "reverse": m.ModifyType = "alter" From 94e79eddcf0ff616fda140b360033389eda5b809 Mon Sep 17 00:00:00 2001 From: Gnanakeethan Balasubramaniam Date: Sun, 16 Jul 2017 08:37:27 +0530 Subject: [PATCH 33/38] Update: removing remnant of revert commit ( a call to function m.DDLSpec() ) Signed-off-by: Gnanakeethan Balasubramaniam --- migration/migration.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migration/migration.go b/migration/migration.go index 0a140b24..51053714 100644 --- a/migration/migration.go +++ b/migration/migration.go @@ -94,7 +94,7 @@ func (m *Migration) Up() { // Down implement in the Inheritance struct for down func (m *Migration) Down() { - m.DDLSpec() + switch m.ModifyType { case "alter": m.ModifyType = "reverse" From 8bb0a70847726f36edd1ac8e8ffcd28899e29fb8 Mon Sep 17 00:00:00 2001 From: Gnanakeethan Balasubramaniam Date: Sun, 16 Jul 2017 08:48:44 +0530 Subject: [PATCH 34/38] Update: Fix in SQL Generation Signed-off-by: Gnanakeethan Balasubramaniam --- migration/ddl.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/migration/ddl.go b/migration/ddl.go index d7d08f9e..01cee196 100644 --- a/migration/ddl.go +++ b/migration/ddl.go @@ -301,14 +301,11 @@ func (m *Migration) GetSQL() (sql string) { } sql += fmt.Sprintf(")") } - for index, foreign := range m.Foreigns { + for _, foreign := range m.Foreigns { sql += fmt.Sprintf(",\n `%s` %s %s %s %s %s", foreign.Name, foreign.DataType, foreign.Unsign, foreign.Null, foreign.Inc, foreign.Default) sql += fmt.Sprintf(",\n KEY `%s_%s_foreign`(`%s`),", m.TableName, foreign.Column.Name, foreign.Column.Name) - sql += fmt.Sprintf("\n CONSTRAINT `%s_%s_foreign` FOREIGN KEY (`%s`) REFERENCES `%s` (`%s`) %s %s", m.TableName, foreign.Column.Name, foreign.Column.Name, foreign.ForeignTable, foreign.ForeignColumn, foreign.OnDelete, foreign.OnUpdate) + sql += fmt.Sprintf("\n CONSTRAINT `%s_%s_foreign` FOREIGN KEY (`%s`) REFERENCES `%s` (`%s`) %s %s", m.TableName, foreign.Column.Name, foreign.Column.Name, foreign.ForeignTable, foreign.ForeignColumn, foreign.OnDelete, foreign.OnUpdate) - if len(m.Foreigns) > index+1 { - sql += "," - } } sql += fmt.Sprintf(")ENGINE=%s DEFAULT CHARSET=%s;", m.Engine, m.Charset) break From b27ab53017e2682887f8f3815d949eb97725f418 Mon Sep 17 00:00:00 2001 From: astaxie Date: Tue, 18 Jul 2017 23:41:50 +0800 Subject: [PATCH 35/38] fix issue for runMethod and runRouter from context --- router.go | 1 - 1 file changed, 1 deletion(-) diff --git a/router.go b/router.go index 874fb109..e5a4e80d 100644 --- a/router.go +++ b/router.go @@ -704,7 +704,6 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) // User can define RunController and RunMethod in filter if context.Input.RunController != nil && context.Input.RunMethod != "" { findRouter = true - isRunnable = true runMethod = context.Input.RunMethod runRouter = context.Input.RunController } else { From 5ac0cb929c22efa7089ae573bf7764af9acd6ccc Mon Sep 17 00:00:00 2001 From: astaxie Date: Tue, 18 Jul 2017 23:58:22 +0800 Subject: [PATCH 36/38] v1.9.0 --- beego.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/beego.go b/beego.go index 218fded8..0512dc60 100644 --- a/beego.go +++ b/beego.go @@ -23,7 +23,7 @@ import ( const ( // VERSION represent beego web framework version. - VERSION = "1.8.3" + VERSION = "1.9.0" // DEV is for develop DEV = "dev" From aa3d6c5363419821f7c175282e8e5476a6fa3cb3 Mon Sep 17 00:00:00 2001 From: astaxie Date: Wed, 19 Jul 2017 00:37:42 +0800 Subject: [PATCH 37/38] fix the gosimple --- error_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/error_test.go b/error_test.go index 2fb8f962..378aa953 100644 --- a/error_test.go +++ b/error_test.go @@ -52,7 +52,7 @@ func TestErrorCode_01(t *testing.T) { if w.Code != code { t.Fail() } - if !strings.Contains(string(w.Body.Bytes()), http.StatusText(code)) { + if !strings.Contains(w.Body.String(), http.StatusText(code)) { t.Fail() } } @@ -82,7 +82,7 @@ func TestErrorCode_03(t *testing.T) { if w.Code != 200 { t.Fail() } - if string(w.Body.Bytes()) != parseCodeError { + if w.Body.String() != parseCodeError { t.Fail() } } From 4fc95b0d691f40578766638d54409ad17f15f6d7 Mon Sep 17 00:00:00 2001 From: astaxie Date: Wed, 19 Jul 2017 00:52:27 +0800 Subject: [PATCH 38/38] gofmt and golint --- controller.go | 1 + grace/conn.go | 4 +-- migration/ddl.go | 1 + migration/doc.go | 71 ++++++++++++++++++---------------------- validation/util.go | 6 ++-- validation/validators.go | 12 +++---- 6 files changed, 44 insertions(+), 51 deletions(-) diff --git a/controller.go b/controller.go index da8e8504..c104eb2a 100644 --- a/controller.go +++ b/controller.go @@ -55,6 +55,7 @@ type ControllerComments struct { MethodParams []*param.MethodParam } +// ControllerCommentsSlice implements the sort interface type ControllerCommentsSlice []ControllerComments func (p ControllerCommentsSlice) Len() int { return len(p) } diff --git a/grace/conn.go b/grace/conn.go index 6f52045f..e020f850 100644 --- a/grace/conn.go +++ b/grace/conn.go @@ -9,7 +9,7 @@ import ( type graceConn struct { net.Conn server *Server - m sync.Mutex + m sync.Mutex closed bool } @@ -26,7 +26,7 @@ func (c *graceConn) Close() (err error) { } } }() - + c.m.Lock() if c.closed { c.m.Unlock() diff --git a/migration/ddl.go b/migration/ddl.go index 01cee196..cea10355 100644 --- a/migration/ddl.go +++ b/migration/ddl.go @@ -71,6 +71,7 @@ func (m *Migration) CreateTable(tablename, engine, charset string, p ...func()) m.ModifyType = "create" } +// AlterTable set the ModifyType to alter func (m *Migration) AlterTable(tablename string) { m.TableName = tablename m.ModifyType = "alter" diff --git a/migration/doc.go b/migration/doc.go index 2d6ccaf6..0c6564d4 100644 --- a/migration/doc.go +++ b/migration/doc.go @@ -1,41 +1,32 @@ -/* Package migration enables you to generate migrations back and forth. It generates both migrations. - - -//Creates a table -m.CreateTable("tablename","InnoDB","utf8"); - - - -//Alter a table -m.AlterTable("tablename") - - - -//Standard Column Methods -* SetDataType -* SetNullable -* SetDefault -* SetUnsigned (use only on integer types unless produces error) - - -//Sets a primary column, multiple calls allowed, standard column methods available -m.PriCol("id").SetAuto(true).SetNullable(false).SetDataType("INT(10)").SetUnsigned(true) - -//UniCol Can be used multiple times, allows standard Column methods. Use same "index" string to add to same index -m.UniCol("index","column") - -//Standard Column Initialisation, can call .Remove() after NewCol("") on alter to remove -m.NewCol("name").SetDataType("VARCHAR(255) COLLATE utf8_unicode_ci").SetNullable(false) -m.NewCol("value").SetDataType("DOUBLE(8,2)").SetNullable(false) - -//Rename Columns , only use with Alter table, doesn't works with Create, prefix standard column methods with "Old" to -//create a true reversible migration eg: SetOldDataType("DOUBLE(12,3)") -m.RenameColumn("from","to")... - - -//Foreign Columns, single columns are only supported, SetOnDelete & SetOnUpdate are available, call appropriately. -//Supports standard column methods, automatic reverse. -m.ForeignCol("local_col","foreign_col","foreign_table") - -*/ +// Package migration enables you to generate migrations back and forth. It generates both migrations. +// +// //Creates a table +// m.CreateTable("tablename","InnoDB","utf8"); +// +// //Alter a table +// m.AlterTable("tablename") +// +// Standard Column Methods +// * SetDataType +// * SetNullable +// * SetDefault +// * SetUnsigned (use only on integer types unless produces error) +// +// //Sets a primary column, multiple calls allowed, standard column methods available +// m.PriCol("id").SetAuto(true).SetNullable(false).SetDataType("INT(10)").SetUnsigned(true) +// +// //UniCol Can be used multiple times, allows standard Column methods. Use same "index" string to add to same index +// m.UniCol("index","column") +// +// //Standard Column Initialisation, can call .Remove() after NewCol("") on alter to remove +// m.NewCol("name").SetDataType("VARCHAR(255) COLLATE utf8_unicode_ci").SetNullable(false) +// m.NewCol("value").SetDataType("DOUBLE(8,2)").SetNullable(false) +// +// //Rename Columns , only use with Alter table, doesn't works with Create, prefix standard column methods with "Old" to +// //create a true reversible migration eg: SetOldDataType("DOUBLE(12,3)") +// m.RenameColumn("from","to")... +// +// //Foreign Columns, single columns are only supported, SetOnDelete & SetOnUpdate are available, call appropriately. +// //Supports standard column methods, automatic reverse. +// m.ForeignCol("local_col","foreign_col","foreign_table") package migration diff --git a/validation/util.go b/validation/util.go index 4695b776..66fce283 100644 --- a/validation/util.go +++ b/validation/util.go @@ -45,8 +45,8 @@ var ( "Valid": true, "NoMatch": true, } - - Int64On32Err = fmt.Errorf("not support int64 on 32-bit platform") + // ErrInt64On32 show 32 bit platform not support int64 + ErrInt64On32 = fmt.Errorf("not support int64 on 32-bit platform") ) func init() { @@ -255,7 +255,7 @@ func parseParam(t reflect.Type, s string) (i interface{}, err error) { i, err = strconv.Atoi(s) case reflect.Int64: if wordsize == 32 { - return nil, Int64On32Err + return nil, ErrInt64On32 } i, err = strconv.ParseInt(s, 10, 64) case reflect.Int32: diff --git a/validation/validators.go b/validation/validators.go index a9c3e6b8..4dff9c0b 100644 --- a/validation/validators.go +++ b/validation/validators.go @@ -25,12 +25,12 @@ import ( // CanSkipFuncs will skip valid if RequiredFirst is true and the struct field's value is empty var CanSkipFuncs = map[string]struct{}{ - "Email": struct{}{}, - "IP": struct{}{}, - "Mobile": struct{}{}, - "Tel": struct{}{}, - "Phone": struct{}{}, - "ZipCode": struct{}{}, + "Email": {}, + "IP": {}, + "Mobile": {}, + "Tel": {}, + "Phone": {}, + "ZipCode": {}, } // MessageTmpls store commond validate template