diff --git a/CHANGELOG.md b/CHANGELOG.md index 61ab75cc..27ac0cc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # developing - [httplib: fix unstable unit test which use the httplib.org](https://github.com/beego/beego/pull/5232) +- [remove adapter package](https://github.com/beego/beego/pull/5239) ## ORM refactoring - [introducing internal/models pkg](https://github.com/beego/beego/pull/5238) diff --git a/client/httplib/client_option_test.go b/client/httplib/client_option_test.go deleted file mode 100644 index 416f092b..00000000 --- a/client/httplib/client_option_test.go +++ /dev/null @@ -1,261 +0,0 @@ -// Copyright 2020 beego -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package httplib - -import ( - "errors" - "net" - "net/http" - "strings" - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -type respCarrier struct { - bytes []byte -} - -func (r *respCarrier) SetBytes(bytes []byte) { - r.bytes = bytes -} - -func (r *respCarrier) String() string { - return string(r.bytes) -} - -func TestOptionWithEnableCookie(t *testing.T) { - client, err := NewClient("test", "http://httpbin.org/", - WithEnableCookie(true)) - if err != nil { - t.Fatal(err) - } - - v := "smallfish" - resp := &respCarrier{} - err = client.Get(resp, "/cookies/set?k1="+v) - if err != nil { - t.Fatal(err) - } - t.Log(resp.String()) - - err = client.Get(resp, "/cookies") - if err != nil { - t.Fatal(err) - } - t.Log(resp.String()) - - n := strings.Index(resp.String(), v) - if n == -1 { - t.Fatal(v + " not found in cookie") - } -} - -func TestOptionWithUserAgent(t *testing.T) { - v := "beego" - client, err := NewClient("test", "http://httpbin.org/", - WithUserAgent(v)) - if err != nil { - t.Fatal(err) - } - - resp := &respCarrier{} - err = client.Get(resp, "/headers") - if err != nil { - t.Fatal(err) - } - t.Log(resp.String()) - - n := strings.Index(resp.String(), v) - if n == -1 { - t.Fatal(v + " not found in user-agent") - } -} - -func TestOptionWithCheckRedirect(t *testing.T) { - client, err := NewClient("test", "https://goolnk.com/33BD2j", - WithCheckRedirect(func(redirectReq *http.Request, redirectVia []*http.Request) error { - return errors.New("Redirect triggered") - })) - if err != nil { - t.Fatal(err) - } - err = client.Get(nil, "") - assert.NotNil(t, err) -} - -func TestOptionWithHTTPSetting(t *testing.T) { - v := "beego" - var setting BeegoHTTPSettings - setting.EnableCookie = true - setting.UserAgent = v - setting.Transport = &http.Transport{ - DialContext: (&net.Dialer{ - Timeout: 30 * time.Second, - KeepAlive: 30 * time.Second, - DualStack: true, - }).DialContext, - MaxIdleConns: 50, - IdleConnTimeout: 90 * time.Second, - ExpectContinueTimeout: 1 * time.Second, - } - setting.ReadWriteTimeout = 5 * time.Second - - client, err := NewClient("test", "http://httpbin.org/", - WithHTTPSetting(setting)) - if err != nil { - t.Fatal(err) - } - - resp := &respCarrier{} - err = client.Get(resp, "/get") - if err != nil { - t.Fatal(err) - } - t.Log(resp.String()) - - n := strings.Index(resp.String(), v) - if n == -1 { - t.Fatal(v + " not found in user-agent") - } -} - -func TestOptionWithHeader(t *testing.T) { - client, err := NewClient("test", "http://httpbin.org/") - if err != nil { - t.Fatal(err) - } - client.CommonOpts = append(client.CommonOpts, WithHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36")) - - resp := &respCarrier{} - err = client.Get(resp, "/headers") - if err != nil { - t.Fatal(err) - } - t.Log(resp.String()) - - n := strings.Index(resp.String(), "Mozilla/5.0") - if n == -1 { - t.Fatal("Mozilla/5.0 not found in user-agent") - } -} - -func TestOptionWithTokenFactory(t *testing.T) { - client, err := NewClient("test", "http://httpbin.org/") - if err != nil { - t.Fatal(err) - } - client.CommonOpts = append(client.CommonOpts, - WithTokenFactory(func() string { - return "testauth" - })) - - resp := &respCarrier{} - err = client.Get(resp, "/headers") - if err != nil { - t.Fatal(err) - } - t.Log(resp.String()) - - n := strings.Index(resp.String(), "testauth") - if n == -1 { - t.Fatal("Auth is not set in request") - } -} - -func TestOptionWithBasicAuth(t *testing.T) { - client, err := NewClient("test", "http://httpbin.org/") - if err != nil { - t.Fatal(err) - } - - resp := &respCarrier{} - err = client.Get(resp, "/basic-auth/user/passwd", - WithBasicAuth(func() (string, string) { - return "user", "passwd" - })) - if err != nil { - t.Fatal(err) - } - t.Log(resp.String()) - n := strings.Index(resp.String(), "authenticated") - if n == -1 { - t.Fatal("authenticated not found in response") - } -} - -func TestOptionWithContentType(t *testing.T) { - client, err := NewClient("test", "http://httpbin.org/") - if err != nil { - t.Fatal(err) - } - - v := "application/json" - resp := &respCarrier{} - err = client.Get(resp, "/headers", WithContentType(v)) - if err != nil { - t.Fatal(err) - } - t.Log(resp.String()) - - n := strings.Index(resp.String(), v) - if n == -1 { - t.Fatal(v + " not found in header") - } -} - -func TestOptionWithParam(t *testing.T) { - client, err := NewClient("test", "http://httpbin.org/") - if err != nil { - t.Fatal(err) - } - - v := "smallfish" - resp := &respCarrier{} - err = client.Get(resp, "/get", WithParam("username", v)) - if err != nil { - t.Fatal(err) - } - t.Log(resp.String()) - - n := strings.Index(resp.String(), v) - if n == -1 { - t.Fatal(v + " not found in header") - } -} - -func TestOptionWithRetry(t *testing.T) { - client, err := NewClient("test", "https://goolnk.com/33BD2j", - WithCheckRedirect(func(redirectReq *http.Request, redirectVia []*http.Request) error { - return errors.New("Redirect triggered") - })) - if err != nil { - t.Fatal(err) - } - - retryAmount := 1 - retryDelay := 800 * time.Millisecond - startTime := time.Now().UnixNano() / int64(time.Millisecond) - - _ = client.Get(nil, "", WithRetry(retryAmount, retryDelay)) - - endTime := time.Now().UnixNano() / int64(time.Millisecond) - elapsedTime := endTime - startTime - delayedTime := int64(retryAmount) * retryDelay.Milliseconds() - if elapsedTime < delayedTime { - t.Errorf("Not enough retries. Took %dms. Delay was meant to take %dms", elapsedTime, delayedTime) - } -} diff --git a/client/orm/cmd.go b/client/orm/cmd.go index fc40381d..cd6fd5cc 100644 --- a/client/orm/cmd.go +++ b/client/orm/cmd.go @@ -21,6 +21,8 @@ import ( "os" "strings" + "github.com/beego/beego/v2/client/orm/internal/utils" + "github.com/beego/beego/v2/client/orm/internal/models" ) @@ -55,7 +57,7 @@ func RunCommand() { BootStrap() - args := argString(os.Args[2:]) + args := utils.ArgString(os.Args[2:]) name := args.Get(0) if name == "help" { diff --git a/client/orm/db.go b/client/orm/db.go index b955594e..e4b53e36 100644 --- a/client/orm/db.go +++ b/client/orm/db.go @@ -23,17 +23,15 @@ import ( "strings" "time" + "github.com/beego/beego/v2/client/orm/internal/logs" + + "github.com/beego/beego/v2/client/orm/internal/utils" + "github.com/beego/beego/v2/client/orm/internal/models" "github.com/beego/beego/v2/client/orm/hints" ) -const ( - formatTime = "15:04:05" - formatDate = "2006-01-02" - formatDateTime = "2006-01-02 15:04:05" -) - // ErrMissPK missing pk error var ErrMissPK = errors.New("missed pk value") @@ -125,7 +123,7 @@ func (d *dbBase) collectFieldValue(mi *models.ModelInfo, fi *models.FieldInfo, i } else { field := ind.FieldByIndex(fi.FieldIndex) if fi.IsFielder { - f := field.Addr().Interface().(Fielder) + f := field.Addr().Interface().(models.Fielder) value = f.RawValue() } else { switch fi.FieldType { @@ -174,7 +172,7 @@ func (d *dbBase) collectFieldValue(mi *models.ModelInfo, fi *models.FieldInfo, i } else { vu := field.Interface() if _, ok := vu.(float32); ok { - value, _ = StrTo(ToStr(vu)).Float64() + value, _ = utils.StrTo(utils.ToStr(vu)).Float64() } else { value = field.Float() } @@ -244,7 +242,7 @@ func (d *dbBase) collectFieldValue(mi *models.ModelInfo, fi *models.FieldInfo, i d.ins.TimeToDB(&tnow, tz) value = tnow if fi.IsFielder { - f := field.Addr().Interface().(Fielder) + f := field.Addr().Interface().(models.Fielder) f.SetRaw(tnow.In(DefaultTimeLoc)) } else if field.Kind() == reflect.Ptr { v := tnow.In(DefaultTimeLoc) @@ -482,7 +480,7 @@ func (d *dbBase) InsertValue(ctx context.Context, q dbQuerier, mi *models.ModelI lastInsertId, err := res.LastInsertId() if err != nil { - DebugLog.Println(ErrLastInsertIdUnavailable, ':', err) + logs.DebugLog.Println(ErrLastInsertIdUnavailable, ':', err) return lastInsertId, ErrLastInsertIdUnavailable } else { return lastInsertId, nil @@ -589,7 +587,7 @@ func (d *dbBase) InsertOrUpdate(ctx context.Context, q dbQuerier, mi *models.Mod lastInsertId, err := res.LastInsertId() if err != nil { - DebugLog.Println(ErrLastInsertIdUnavailable, ':', err) + logs.DebugLog.Println(ErrLastInsertIdUnavailable, ':', err) return lastInsertId, ErrLastInsertIdUnavailable } else { return lastInsertId, nil @@ -1201,7 +1199,7 @@ func (d *dbBase) GenerateOperatorSQL(mi *models.ModelInfo, fi *models.FieldInfo, params[0] = "IS NULL" } case "iexact", "contains", "icontains", "startswith", "endswith", "istartswith", "iendswith": - param := strings.Replace(ToStr(arg), `%`, `\%`, -1) + param := strings.Replace(utils.ToStr(arg), `%`, `\%`, -1) switch operator { case "iexact": case "contains", "icontains": @@ -1264,13 +1262,13 @@ func (d *dbBase) convertValueFromDB(fi *models.FieldInfo, val interface{}, tz *t var value interface{} var tErr error - var str *StrTo + var str *utils.StrTo switch v := val.(type) { case []byte: - s := StrTo(string(v)) + s := utils.StrTo(string(v)) str = &s case string: - s := StrTo(v) + s := utils.StrTo(v) str = &s } @@ -1285,7 +1283,7 @@ setValue: b := v == 1 value = b default: - s := StrTo(ToStr(v)) + s := utils.StrTo(utils.ToStr(v)) str = &s } } @@ -1299,7 +1297,7 @@ setValue: } case fieldType == TypeVarCharField || fieldType == TypeCharField || fieldType == TypeTextField || fieldType == TypeJSONField || fieldType == TypeJsonbField: if str == nil { - value = ToStr(val) + value = utils.ToStr(val) } else { value = str.String() } @@ -1310,7 +1308,7 @@ setValue: d.ins.TimeFromDB(&t, tz) value = t default: - s := StrTo(ToStr(t)) + s := utils.StrTo(utils.ToStr(t)) str = &s } } @@ -1322,24 +1320,24 @@ setValue: ) if fi.TimePrecision != nil && len(s) >= (20+*fi.TimePrecision) { - layout := formatDateTime + "." + layout := utils.FormatDateTime + "." for i := 0; i < *fi.TimePrecision; i++ { layout += "0" } t, err = time.ParseInLocation(layout, s[:20+*fi.TimePrecision], tz) } else if len(s) >= 19 { s = s[:19] - t, err = time.ParseInLocation(formatDateTime, s, tz) + t, err = time.ParseInLocation(utils.FormatDateTime, s, tz) } else if len(s) >= 10 { if len(s) > 10 { s = s[:10] } - t, err = time.ParseInLocation(formatDate, s, tz) + t, err = time.ParseInLocation(utils.FormatDate, s, tz) } else if len(s) >= 8 { if len(s) > 8 { s = s[:8] } - t, err = time.ParseInLocation(formatTime, s, tz) + t, err = time.ParseInLocation(utils.FormatTime, s, tz) } t = t.In(DefaultTimeLoc) @@ -1351,7 +1349,7 @@ setValue: } case fieldType&IsIntegerField > 0: if str == nil { - s := StrTo(ToStr(val)) + s := utils.StrTo(utils.ToStr(val)) str = &s } if str != nil { @@ -1392,7 +1390,7 @@ setValue: case float64: value = v default: - s := StrTo(ToStr(v)) + s := utils.StrTo(utils.ToStr(v)) str = &s } } @@ -1599,7 +1597,7 @@ setValue: } if !isNative { - fd := field.Addr().Interface().(Fielder) + fd := field.Addr().Interface().(models.Fielder) err := fd.SetRaw(value) if err != nil { err = fmt.Errorf("converted value `%v` set to Fielder `%s` failed, err: %s", value, fi.FullName, err) @@ -1918,7 +1916,7 @@ func (d *dbBase) GenerateSpecifyIndex(tableName string, useIndex int, indexes [] case hints.KeyIgnoreIndex: useWay = `IGNORE` default: - DebugLog.Println("[WARN] Not a valid specifying action, so that action is ignored") + logs.DebugLog.Println("[WARN] Not a valid specifying action, so that action is ignored") return `` } diff --git a/client/orm/db_alias.go b/client/orm/db_alias.go index 28c8ab8e..ff0b962f 100644 --- a/client/orm/db_alias.go +++ b/client/orm/db_alias.go @@ -21,6 +21,8 @@ import ( "sync" "time" + "github.com/beego/beego/v2/client/orm/internal/logs" + lru "github.com/hashicorp/golang-lru" ) @@ -320,7 +322,7 @@ func detectTZ(al *alias) { al.TZ = t.Location() } } else { - DebugLog.Printf("Detect DB timezone: %s %s\n", tz, err.Error()) + logs.DebugLog.Printf("Detect DB timezone: %s %s\n", tz, err.Error()) } } @@ -347,7 +349,7 @@ func detectTZ(al *alias) { if err == nil { al.TZ = loc } else { - DebugLog.Printf("Detect DB timezone: %s %s\n", tz, err.Error()) + logs.DebugLog.Printf("Detect DB timezone: %s %s\n", tz, err.Error()) } } } @@ -479,7 +481,7 @@ end: if db != nil { db.Close() } - DebugLog.Println(err.Error()) + logs.DebugLog.Println(err.Error()) } return err diff --git a/client/orm/db_mysql.go b/client/orm/db_mysql.go index 35f6246b..889d807f 100644 --- a/client/orm/db_mysql.go +++ b/client/orm/db_mysql.go @@ -20,6 +20,8 @@ import ( "reflect" "strings" + "github.com/beego/beego/v2/client/orm/internal/logs" + "github.com/beego/beego/v2/client/orm/internal/models" ) @@ -161,7 +163,7 @@ func (d *dbBaseMysql) InsertOrUpdate(ctx context.Context, q dbQuerier, mi *model if err == nil { lastInsertId, err := res.LastInsertId() if err != nil { - DebugLog.Println(ErrLastInsertIdUnavailable, ':', err) + logs.DebugLog.Println(ErrLastInsertIdUnavailable, ':', err) return lastInsertId, ErrLastInsertIdUnavailable } else { return lastInsertId, nil diff --git a/client/orm/db_oracle.go b/client/orm/db_oracle.go index aab2a44f..5057f358 100644 --- a/client/orm/db_oracle.go +++ b/client/orm/db_oracle.go @@ -19,6 +19,8 @@ import ( "fmt" "strings" + "github.com/beego/beego/v2/client/orm/internal/logs" + "github.com/beego/beego/v2/client/orm/internal/models" "github.com/beego/beego/v2/client/orm/hints" @@ -118,7 +120,7 @@ func (d *dbBaseOracle) GenerateSpecifyIndex(tableName string, useIndex int, inde case hints.KeyIgnoreIndex: hint = `NO_INDEX` default: - DebugLog.Println("[WARN] Not a valid specifying action, so that action is ignored") + logs.DebugLog.Println("[WARN] Not a valid specifying action, so that action is ignored") return `` } @@ -158,7 +160,7 @@ func (d *dbBaseOracle) InsertValue(ctx context.Context, q dbQuerier, mi *models. lastInsertId, err := res.LastInsertId() if err != nil { - DebugLog.Println(ErrLastInsertIdUnavailable, ':', err) + logs.DebugLog.Println(ErrLastInsertIdUnavailable, ':', err) return lastInsertId, ErrLastInsertIdUnavailable } else { return lastInsertId, nil diff --git a/client/orm/db_postgres.go b/client/orm/db_postgres.go index 5ccc909f..b52b2578 100644 --- a/client/orm/db_postgres.go +++ b/client/orm/db_postgres.go @@ -19,6 +19,8 @@ import ( "fmt" "strconv" + "github.com/beego/beego/v2/client/orm/internal/logs" + "github.com/beego/beego/v2/client/orm/internal/models" ) @@ -187,7 +189,7 @@ func (d *dbBasePostgres) IndexExists(ctx context.Context, db dbQuerier, table st // GenerateSpecifyIndex return a specifying index clause func (d *dbBasePostgres) GenerateSpecifyIndex(tableName string, useIndex int, indexes []string) string { - DebugLog.Println("[WARN] Not support any specifying index action, so that action is ignored") + logs.DebugLog.Println("[WARN] Not support any specifying index action, so that action is ignored") return `` } diff --git a/client/orm/db_sqlite.go b/client/orm/db_sqlite.go index 7f7c5694..e353404e 100644 --- a/client/orm/db_sqlite.go +++ b/client/orm/db_sqlite.go @@ -22,6 +22,8 @@ import ( "strings" "time" + "github.com/beego/beego/v2/client/orm/internal/logs" + "github.com/beego/beego/v2/client/orm/internal/models" "github.com/beego/beego/v2/client/orm/hints" @@ -78,7 +80,7 @@ var _ dbBaser = new(dbBaseSqlite) // override base db read for update behavior as SQlite does not support syntax func (d *dbBaseSqlite) Read(ctx context.Context, q dbQuerier, mi *models.ModelInfo, ind reflect.Value, tz *time.Location, cols []string, isForUpdate bool) error { if isForUpdate { - DebugLog.Println("[WARN] SQLite does not support SELECT FOR UPDATE query, isForUpdate param is ignored and always as false to do the work") + logs.DebugLog.Println("[WARN] SQLite does not support SELECT FOR UPDATE query, isForUpdate param is ignored and always as false to do the work") } return d.dbBase.Read(ctx, q, mi, ind, tz, cols, false) } @@ -173,7 +175,7 @@ func (d *dbBaseSqlite) GenerateSpecifyIndex(tableName string, useIndex int, inde case hints.KeyUseIndex, hints.KeyForceIndex: return fmt.Sprintf(` INDEXED BY %s `, strings.Join(s, `,`)) default: - DebugLog.Println("[WARN] Not a valid specifying action, so that action is ignored") + logs.DebugLog.Println("[WARN] Not a valid specifying action, so that action is ignored") return `` } } diff --git a/client/orm/db_utils.go b/client/orm/db_utils.go index 93218468..45c95f85 100644 --- a/client/orm/db_utils.go +++ b/client/orm/db_utils.go @@ -19,6 +19,8 @@ import ( "reflect" "time" + "github.com/beego/beego/v2/client/orm/internal/utils" + "github.com/beego/beego/v2/client/orm/internal/models" ) @@ -81,27 +83,27 @@ outFor: var err error if len(v) >= 19 { s := v[:19] - t, err = time.ParseInLocation(formatDateTime, s, DefaultTimeLoc) + t, err = time.ParseInLocation(utils.FormatDateTime, s, DefaultTimeLoc) } else if len(v) >= 10 { s := v if len(v) > 10 { s = v[:10] } - t, err = time.ParseInLocation(formatDate, s, tz) + t, err = time.ParseInLocation(utils.FormatDate, s, tz) } else { s := v if len(s) > 8 { s = v[:8] } - t, err = time.ParseInLocation(formatTime, s, tz) + t, err = time.ParseInLocation(utils.FormatTime, s, tz) } if err == nil { if fi.FieldType == TypeDateField { - v = t.In(tz).Format(formatDate) + v = t.In(tz).Format(utils.FormatDate) } else if fi.FieldType == TypeDateTimeField { - v = t.In(tz).Format(formatDateTime) + v = t.In(tz).Format(utils.FormatDateTime) } else { - v = t.In(tz).Format(formatTime) + v = t.In(tz).Format(utils.FormatTime) } } } @@ -112,7 +114,7 @@ outFor: case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: arg = val.Uint() case reflect.Float32: - arg, _ = StrTo(ToStr(arg)).Float64() + arg, _ = utils.StrTo(utils.ToStr(arg)).Float64() case reflect.Float64: arg = val.Float() case reflect.Bool: @@ -146,13 +148,13 @@ outFor: case reflect.Struct: if v, ok := arg.(time.Time); ok { if fi != nil && fi.FieldType == TypeDateField { - arg = v.In(tz).Format(formatDate) + arg = v.In(tz).Format(utils.FormatDate) } else if fi != nil && fi.FieldType == TypeDateTimeField { - arg = v.In(tz).Format(formatDateTime) + arg = v.In(tz).Format(utils.FormatDateTime) } else if fi != nil && fi.FieldType == TypeTimeField { - arg = v.In(tz).Format(formatTime) + arg = v.In(tz).Format(utils.FormatTime) } else { - arg = v.In(tz).Format(formatDateTime) + arg = v.In(tz).Format(utils.FormatDateTime) } } else { typ := val.Type() diff --git a/client/orm/filter_orm_decorator.go b/client/orm/filter_orm_decorator.go index da90c89a..c8a28967 100644 --- a/client/orm/filter_orm_decorator.go +++ b/client/orm/filter_orm_decorator.go @@ -20,6 +20,8 @@ import ( "reflect" "time" + utils2 "github.com/beego/beego/v2/client/orm/internal/utils" + "github.com/beego/beego/v2/client/orm/internal/models" "github.com/beego/beego/v2/core/logs" @@ -200,7 +202,7 @@ func (f *filterOrmDecorator) QueryTable(ptrStructOrTableName interface{}) QueryS if table, ok := ptrStructOrTableName.(string); ok { name = table } else { - name = models.GetFullName(indirectType(reflect.TypeOf(ptrStructOrTableName))) + name = models.GetFullName(utils2.IndirectType(reflect.TypeOf(ptrStructOrTableName))) md = ptrStructOrTableName } diff --git a/client/orm/internal/logs/log.go b/client/orm/internal/logs/log.go new file mode 100644 index 00000000..3ddde3ad --- /dev/null +++ b/client/orm/internal/logs/log.go @@ -0,0 +1,20 @@ +package logs + +import ( + "io" + "log" + "os" +) + +var DebugLog = NewLog(os.Stdout) + +// Log implement the log.Logger +type Log struct { + *log.Logger +} + +func NewLog(out io.Writer) *Log { + d := new(Log) + d.Logger = log.New(out, "[ORM]", log.LstdFlags) + return d +} diff --git a/client/orm/internal/models/models_fields.go b/client/orm/internal/models/models_fields.go new file mode 100644 index 00000000..70e5aafa --- /dev/null +++ b/client/orm/internal/models/models_fields.go @@ -0,0 +1,785 @@ +// Copyright 2014 beego Author. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package models + +import ( + "fmt" + "strconv" + "time" + + "github.com/beego/beego/v2/client/orm/internal/utils" +) + +// Define the Type enum +const ( + TypeBooleanField = 1 << iota + TypeVarCharField + TypeCharField + TypeTextField + TypeTimeField + TypeDateField + TypeDateTimeField + TypeBitField + TypeSmallIntegerField + TypeIntegerField + TypeBigIntegerField + TypePositiveBitField + TypePositiveSmallIntegerField + TypePositiveIntegerField + TypePositiveBigIntegerField + TypeFloatField + TypeDecimalField + TypeJSONField + TypeJsonbField + RelForeignKey + RelOneToOne + RelManyToMany + RelReverseOne + RelReverseMany +) + +// Define some logic enum +const ( + IsIntegerField = ^-TypePositiveBigIntegerField >> 6 << 7 + IsPositiveIntegerField = ^-TypePositiveBigIntegerField >> 10 << 11 + IsRelField = ^-RelReverseMany >> 18 << 19 + IsFieldType = ^-RelReverseMany<<1 + 1 +) + +// BooleanField A true/false field. +type BooleanField bool + +// Value return the BooleanField +func (e BooleanField) Value() bool { + return bool(e) +} + +// Set will set the BooleanField +func (e *BooleanField) Set(d bool) { + *e = BooleanField(d) +} + +// String format the Bool to string +func (e *BooleanField) String() string { + return strconv.FormatBool(e.Value()) +} + +// FieldType return BooleanField the type +func (e *BooleanField) FieldType() int { + return TypeBooleanField +} + +// SetRaw set the interface to bool +func (e *BooleanField) SetRaw(value interface{}) error { + switch d := value.(type) { + case bool: + e.Set(d) + case string: + v, err := utils.StrTo(d).Bool() + if err == nil { + e.Set(v) + } + return err + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil +} + +// RawValue return the current value +func (e *BooleanField) RawValue() interface{} { + return e.Value() +} + +// verify the BooleanField implement the Fielder interface +var _ Fielder = new(BooleanField) + +// CharField A string field +// required values tag: size +// The size is enforced at the database level and in models’s validation. +// eg: `orm:"size(120)"` +type CharField string + +// Value return the CharField's Value +func (e CharField) Value() string { + return string(e) +} + +// Set CharField value +func (e *CharField) Set(d string) { + *e = CharField(d) +} + +// String return the CharField +func (e *CharField) String() string { + return e.Value() +} + +// FieldType return the enum type +func (e *CharField) FieldType() int { + return TypeVarCharField +} + +// SetRaw set the interface to string +func (e *CharField) SetRaw(value interface{}) error { + switch d := value.(type) { + case string: + e.Set(d) + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil +} + +// RawValue return the CharField value +func (e *CharField) RawValue() interface{} { + return e.Value() +} + +// verify CharField implement Fielder +var _ Fielder = new(CharField) + +// TimeField A time, represented in go by a time.Time instance. +// only time values like 10:00:00 +// Has a few extra, optional attr tag: +// +// auto_now: +// Automatically set the field to now every time the object is saved. Useful for “last-modified” timestamps. +// Note that the current date is always used; it’s not just a default value that you can override. +// +// auto_now_add: +// Automatically set the field to now when the object is first created. Useful for creation of timestamps. +// Note that the current date is always used; it’s not just a default value that you can override. +// +// eg: `orm:"auto_now"` or `orm:"auto_now_add"` +type TimeField time.Time + +// Value return the time.Time +func (e TimeField) Value() time.Time { + return time.Time(e) +} + +// Set set the TimeField's value +func (e *TimeField) Set(d time.Time) { + *e = TimeField(d) +} + +// String convert time to string +func (e *TimeField) String() string { + return e.Value().String() +} + +// FieldType return enum type Date +func (e *TimeField) FieldType() int { + return TypeDateField +} + +// SetRaw convert the interface to time.Time. Allow string and time.Time +func (e *TimeField) SetRaw(value interface{}) error { + switch d := value.(type) { + case time.Time: + e.Set(d) + case string: + v, err := utils.TimeParse(d, utils.FormatTime) + if err == nil { + e.Set(v) + } + return err + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil +} + +// RawValue return time value +func (e *TimeField) RawValue() interface{} { + return e.Value() +} + +var _ Fielder = new(TimeField) + +// DateField A date, represented in go by a time.Time instance. +// only date values like 2006-01-02 +// Has a few extra, optional attr tag: +// +// auto_now: +// Automatically set the field to now every time the object is saved. Useful for “last-modified” timestamps. +// Note that the current date is always used; it’s not just a default value that you can override. +// +// auto_now_add: +// Automatically set the field to now when the object is first created. Useful for creation of timestamps. +// Note that the current date is always used; it’s not just a default value that you can override. +// +// eg: `orm:"auto_now"` or `orm:"auto_now_add"` +type DateField time.Time + +// Value return the time.Time +func (e DateField) Value() time.Time { + return time.Time(e) +} + +// Set set the DateField's value +func (e *DateField) Set(d time.Time) { + *e = DateField(d) +} + +// String convert datetime to string +func (e *DateField) String() string { + return e.Value().String() +} + +// FieldType return enum type Date +func (e *DateField) FieldType() int { + return TypeDateField +} + +// SetRaw convert the interface to time.Time. Allow string and time.Time +func (e *DateField) SetRaw(value interface{}) error { + switch d := value.(type) { + case time.Time: + e.Set(d) + case string: + v, err := utils.TimeParse(d, utils.FormatDate) + if err == nil { + e.Set(v) + } + return err + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil +} + +// RawValue return Date value +func (e *DateField) RawValue() interface{} { + return e.Value() +} + +// verify DateField implement fielder interface +var _ Fielder = new(DateField) + +// DateTimeField A date, represented in go by a time.Time instance. +// datetime values like 2006-01-02 15:04:05 +// Takes the same extra arguments as DateField. +type DateTimeField time.Time + +// Value return the datetime value +func (e DateTimeField) Value() time.Time { + return time.Time(e) +} + +// Set set the time.Time to datetime +func (e *DateTimeField) Set(d time.Time) { + *e = DateTimeField(d) +} + +// String return the time's String +func (e *DateTimeField) String() string { + return e.Value().String() +} + +// FieldType return the enum TypeDateTimeField +func (e *DateTimeField) FieldType() int { + return TypeDateTimeField +} + +// SetRaw convert the string or time.Time to DateTimeField +func (e *DateTimeField) SetRaw(value interface{}) error { + switch d := value.(type) { + case time.Time: + e.Set(d) + case string: + v, err := utils.TimeParse(d, utils.FormatDateTime) + if err == nil { + e.Set(v) + } + return err + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil +} + +// RawValue return the datetime value +func (e *DateTimeField) RawValue() interface{} { + return e.Value() +} + +// verify datetime implement fielder +var _ Fielder = new(DateTimeField) + +// FloatField A floating-point number represented in go by a float32 value. +type FloatField float64 + +// Value return the FloatField value +func (e FloatField) Value() float64 { + return float64(e) +} + +// Set the Float64 +func (e *FloatField) Set(d float64) { + *e = FloatField(d) +} + +// String return the string +func (e *FloatField) String() string { + return utils.ToStr(e.Value(), -1, 32) +} + +// FieldType return the enum type +func (e *FloatField) FieldType() int { + return TypeFloatField +} + +// SetRaw converter interface Float64 float32 or string to FloatField +func (e *FloatField) SetRaw(value interface{}) error { + switch d := value.(type) { + case float32: + e.Set(float64(d)) + case float64: + e.Set(d) + case string: + v, err := utils.StrTo(d).Float64() + if err == nil { + e.Set(v) + } + return err + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil +} + +// RawValue return the FloatField value +func (e *FloatField) RawValue() interface{} { + return e.Value() +} + +// verify FloatField implement Fielder +var _ Fielder = new(FloatField) + +// SmallIntegerField -32768 to 32767 +type SmallIntegerField int16 + +// Value return int16 value +func (e SmallIntegerField) Value() int16 { + return int16(e) +} + +// Set the SmallIntegerField value +func (e *SmallIntegerField) Set(d int16) { + *e = SmallIntegerField(d) +} + +// String convert smallint to string +func (e *SmallIntegerField) String() string { + return utils.ToStr(e.Value()) +} + +// FieldType return enum type SmallIntegerField +func (e *SmallIntegerField) FieldType() int { + return TypeSmallIntegerField +} + +// SetRaw convert interface int16/string to int16 +func (e *SmallIntegerField) SetRaw(value interface{}) error { + switch d := value.(type) { + case int16: + e.Set(d) + case string: + v, err := utils.StrTo(d).Int16() + if err == nil { + e.Set(v) + } + return err + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil +} + +// RawValue return smallint value +func (e *SmallIntegerField) RawValue() interface{} { + return e.Value() +} + +// verify SmallIntegerField implement Fielder +var _ Fielder = new(SmallIntegerField) + +// IntegerField -2147483648 to 2147483647 +type IntegerField int32 + +// Value return the int32 +func (e IntegerField) Value() int32 { + return int32(e) +} + +// Set IntegerField value +func (e *IntegerField) Set(d int32) { + *e = IntegerField(d) +} + +// String convert Int32 to string +func (e *IntegerField) String() string { + return utils.ToStr(e.Value()) +} + +// FieldType return the enum type +func (e *IntegerField) FieldType() int { + return TypeIntegerField +} + +// SetRaw convert interface int32/string to int32 +func (e *IntegerField) SetRaw(value interface{}) error { + switch d := value.(type) { + case int32: + e.Set(d) + case string: + v, err := utils.StrTo(d).Int32() + if err == nil { + e.Set(v) + } + return err + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil +} + +// RawValue return IntegerField value +func (e *IntegerField) RawValue() interface{} { + return e.Value() +} + +// verify IntegerField implement Fielder +var _ Fielder = new(IntegerField) + +// BigIntegerField -9223372036854775808 to 9223372036854775807. +type BigIntegerField int64 + +// Value return int64 +func (e BigIntegerField) Value() int64 { + return int64(e) +} + +// Set the BigIntegerField value +func (e *BigIntegerField) Set(d int64) { + *e = BigIntegerField(d) +} + +// String convert BigIntegerField to string +func (e *BigIntegerField) String() string { + return utils.ToStr(e.Value()) +} + +// FieldType return enum type +func (e *BigIntegerField) FieldType() int { + return TypeBigIntegerField +} + +// SetRaw convert interface int64/string to int64 +func (e *BigIntegerField) SetRaw(value interface{}) error { + switch d := value.(type) { + case int64: + e.Set(d) + case string: + v, err := utils.StrTo(d).Int64() + if err == nil { + e.Set(v) + } + return err + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil +} + +// RawValue return BigIntegerField value +func (e *BigIntegerField) RawValue() interface{} { + return e.Value() +} + +// verify BigIntegerField implement Fielder +var _ Fielder = new(BigIntegerField) + +// PositiveSmallIntegerField 0 to 65535 +type PositiveSmallIntegerField uint16 + +// Value return uint16 +func (e PositiveSmallIntegerField) Value() uint16 { + return uint16(e) +} + +// Set PositiveSmallIntegerField value +func (e *PositiveSmallIntegerField) Set(d uint16) { + *e = PositiveSmallIntegerField(d) +} + +// String convert uint16 to string +func (e *PositiveSmallIntegerField) String() string { + return utils.ToStr(e.Value()) +} + +// FieldType return enum type +func (e *PositiveSmallIntegerField) FieldType() int { + return TypePositiveSmallIntegerField +} + +// SetRaw convert Interface uint16/string to uint16 +func (e *PositiveSmallIntegerField) SetRaw(value interface{}) error { + switch d := value.(type) { + case uint16: + e.Set(d) + case string: + v, err := utils.StrTo(d).Uint16() + if err == nil { + e.Set(v) + } + return err + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil +} + +// RawValue returns PositiveSmallIntegerField value +func (e *PositiveSmallIntegerField) RawValue() interface{} { + return e.Value() +} + +// verify PositiveSmallIntegerField implement Fielder +var _ Fielder = new(PositiveSmallIntegerField) + +// PositiveIntegerField 0 to 4294967295 +type PositiveIntegerField uint32 + +// Value return PositiveIntegerField value. Uint32 +func (e PositiveIntegerField) Value() uint32 { + return uint32(e) +} + +// Set the PositiveIntegerField value +func (e *PositiveIntegerField) Set(d uint32) { + *e = PositiveIntegerField(d) +} + +// String convert PositiveIntegerField to string +func (e *PositiveIntegerField) String() string { + return utils.ToStr(e.Value()) +} + +// FieldType return enum type +func (e *PositiveIntegerField) FieldType() int { + return TypePositiveIntegerField +} + +// SetRaw convert interface uint32/string to Uint32 +func (e *PositiveIntegerField) SetRaw(value interface{}) error { + switch d := value.(type) { + case uint32: + e.Set(d) + case string: + v, err := utils.StrTo(d).Uint32() + if err == nil { + e.Set(v) + } + return err + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil +} + +// RawValue return the PositiveIntegerField Value +func (e *PositiveIntegerField) RawValue() interface{} { + return e.Value() +} + +// verify PositiveIntegerField implement Fielder +var _ Fielder = new(PositiveIntegerField) + +// PositiveBigIntegerField 0 to 18446744073709551615 +type PositiveBigIntegerField uint64 + +// Value return uint64 +func (e PositiveBigIntegerField) Value() uint64 { + return uint64(e) +} + +// Set PositiveBigIntegerField value +func (e *PositiveBigIntegerField) Set(d uint64) { + *e = PositiveBigIntegerField(d) +} + +// String convert PositiveBigIntegerField to string +func (e *PositiveBigIntegerField) String() string { + return utils.ToStr(e.Value()) +} + +// FieldType return enum type +func (e *PositiveBigIntegerField) FieldType() int { + return TypePositiveIntegerField +} + +// SetRaw convert interface uint64/string to Uint64 +func (e *PositiveBigIntegerField) SetRaw(value interface{}) error { + switch d := value.(type) { + case uint64: + e.Set(d) + case string: + v, err := utils.StrTo(d).Uint64() + if err == nil { + e.Set(v) + } + return err + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil +} + +// RawValue return PositiveBigIntegerField value +func (e *PositiveBigIntegerField) RawValue() interface{} { + return e.Value() +} + +// verify PositiveBigIntegerField implement Fielder +var _ Fielder = new(PositiveBigIntegerField) + +// TextField A large text field. +type TextField string + +// Value return TextField value +func (e TextField) Value() string { + return string(e) +} + +// Set the TextField value +func (e *TextField) Set(d string) { + *e = TextField(d) +} + +// String convert TextField to string +func (e *TextField) String() string { + return e.Value() +} + +// FieldType return enum type +func (e *TextField) FieldType() int { + return TypeTextField +} + +// SetRaw convert interface string to string +func (e *TextField) SetRaw(value interface{}) error { + switch d := value.(type) { + case string: + e.Set(d) + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil +} + +// RawValue return TextField value +func (e *TextField) RawValue() interface{} { + return e.Value() +} + +// verify TextField implement Fielder +var _ Fielder = new(TextField) + +// JSONField postgres json field. +type JSONField string + +// Value return JSONField value +func (j JSONField) Value() string { + return string(j) +} + +// Set the JSONField value +func (j *JSONField) Set(d string) { + *j = JSONField(d) +} + +// String convert JSONField to string +func (j *JSONField) String() string { + return j.Value() +} + +// FieldType return enum type +func (j *JSONField) FieldType() int { + return TypeJSONField +} + +// SetRaw convert interface string to string +func (j *JSONField) SetRaw(value interface{}) error { + switch d := value.(type) { + case string: + j.Set(d) + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil +} + +// RawValue return JSONField value +func (j *JSONField) RawValue() interface{} { + return j.Value() +} + +// verify JSONField implement Fielder +var _ Fielder = new(JSONField) + +// JsonbField postgres json field. +type JsonbField string + +// Value return JsonbField value +func (j JsonbField) Value() string { + return string(j) +} + +// Set the JsonbField value +func (j *JsonbField) Set(d string) { + *j = JsonbField(d) +} + +// String convert JsonbField to string +func (j *JsonbField) String() string { + return j.Value() +} + +// FieldType return enum type +func (j *JsonbField) FieldType() int { + return TypeJsonbField +} + +// SetRaw convert interface string to string +func (j *JsonbField) SetRaw(value interface{}) error { + switch d := value.(type) { + case string: + j.Set(d) + default: + return fmt.Errorf(" unknown value `%s`", value) + } + return nil +} + +// RawValue return JsonbField value +func (j *JsonbField) RawValue() interface{} { + return j.Value() +} + +// verify JsonbField implement Fielder +var _ Fielder = new(JsonbField) diff --git a/client/orm/internal/models/models_info_f.go b/client/orm/internal/models/models_info_f.go index 3d111a10..3e5e4d6b 100644 --- a/client/orm/internal/models/models_info_f.go +++ b/client/orm/internal/models/models_info_f.go @@ -20,7 +20,7 @@ import ( "reflect" "strings" - "github.com/beego/beego/v2/client/orm" + "github.com/beego/beego/v2/client/orm/internal/utils" ) var errSkipField = errors.New("skip field") @@ -125,7 +125,7 @@ type FieldInfo struct { Column string AddrValue reflect.Value Sf reflect.StructField - Initial orm.StrTo // store the default value + Initial utils.StrTo // store the default value Size int ReverseField string ReverseFieldInfo *FieldInfo @@ -147,7 +147,7 @@ func NewFieldInfo(mi *ModelInfo, field reflect.Value, sf reflect.StructField, mN var ( tag string tagValue string - initial orm.StrTo // store the default value + initial utils.StrTo // store the default value fieldType int attrs map[string]bool tags map[string]string @@ -163,7 +163,7 @@ func NewFieldInfo(mi *ModelInfo, field reflect.Value, sf reflect.StructField, mN addrField = field if field.CanAddr() && field.Kind() != reflect.Ptr { addrField = field.Addr() - if _, ok := addrField.Interface().(orm.Fielder); !ok { + if _, ok := addrField.Interface().(Fielder); !ok { if field.Kind() == reflect.Slice { addrField = field } @@ -188,14 +188,14 @@ func NewFieldInfo(mi *ModelInfo, field reflect.Value, sf reflect.StructField, mN checkType: switch f := addrField.Interface().(type) { - case orm.Fielder: + case Fielder: fi.IsFielder = true if field.Kind() == reflect.Ptr { err = fmt.Errorf("the model Fielder can not be use ptr") goto end } fieldType = f.FieldType() - if fieldType&orm.IsRelField > 0 { + if fieldType&IsRelField > 0 { err = fmt.Errorf("unsupport type custom field, please refer to https://github.com/beego/beego/v2/blob/master/orm/models_fields.go#L24-L42") goto end } @@ -205,13 +205,13 @@ checkType: if tagValue != "" { switch tagValue { case "fk": - fieldType = orm.RelForeignKey + fieldType = RelForeignKey break checkType case "one": - fieldType = orm.RelOneToOne + fieldType = RelOneToOne break checkType case "m2m": - fieldType = orm.RelManyToMany + fieldType = RelManyToMany if tv := tags["rel_table"]; tv != "" { fi.RelTable = tv } else if tv := tags["rel_through"]; tv != "" { @@ -228,10 +228,10 @@ checkType: if tagValue != "" { switch tagValue { case "one": - fieldType = orm.RelReverseOne + fieldType = RelReverseOne break checkType case "many": - fieldType = orm.RelReverseMany + fieldType = RelReverseMany if tv := tags["rel_table"]; tv != "" { fi.RelTable = tv } else if tv := tags["rel_through"]; tv != "" { @@ -248,26 +248,26 @@ checkType: if err != nil { goto end } - if fieldType == orm.TypeVarCharField { + if fieldType == TypeVarCharField { switch tags["type"] { case "char": - fieldType = orm.TypeCharField + fieldType = TypeCharField case "text": - fieldType = orm.TypeTextField + fieldType = TypeTextField case "json": - fieldType = orm.TypeJSONField + fieldType = TypeJSONField case "jsonb": - fieldType = orm.TypeJsonbField + fieldType = TypeJsonbField } } - if fieldType == orm.TypeFloatField && (digits != "" || decimals != "") { - fieldType = orm.TypeDecimalField + if fieldType == TypeFloatField && (digits != "" || decimals != "") { + fieldType = TypeDecimalField } - if fieldType == orm.TypeDateTimeField && tags["type"] == "date" { - fieldType = orm.TypeDateField + if fieldType == TypeDateTimeField && tags["type"] == "date" { + fieldType = TypeDateField } - if fieldType == orm.TypeTimeField && tags["type"] == "time" { - fieldType = orm.TypeTimeField + if fieldType == TypeTimeField && tags["type"] == "time" { + fieldType = TypeTimeField } } @@ -275,12 +275,12 @@ checkType: // rel should Ptr // reverse should slice []*struct switch fieldType { - case orm.RelForeignKey, orm.RelOneToOne, orm.RelReverseOne: + case RelForeignKey, RelOneToOne, RelReverseOne: if field.Kind() != reflect.Ptr { err = fmt.Errorf("rel/reverse:one field must be *%s", field.Type().Name()) goto end } - case orm.RelManyToMany, orm.RelReverseMany: + case RelManyToMany, RelReverseMany: if field.Kind() != reflect.Slice { err = fmt.Errorf("rel/reverse:many field must be slice") goto end @@ -292,7 +292,7 @@ checkType: } } - if fieldType&orm.IsFieldType == 0 { + if fieldType&IsFieldType == 0 { err = fmt.Errorf("wrong field type") goto end } @@ -317,7 +317,7 @@ checkType: } switch fieldType { - case orm.RelManyToMany, orm.RelReverseMany, orm.RelReverseOne: + case RelManyToMany, RelReverseMany, RelReverseOne: fi.Null = false fi.Index = false fi.Auto = false @@ -328,12 +328,12 @@ checkType: } switch fieldType { - case orm.RelForeignKey, orm.RelOneToOne, orm.RelManyToMany: + case RelForeignKey, RelOneToOne, RelManyToMany: fi.Rel = true - if fieldType == orm.RelOneToOne { + if fieldType == RelOneToOne { fi.Unique = true } - case orm.RelReverseMany, orm.RelReverseOne: + case RelReverseMany, RelReverseOne: fi.Reverse = true } @@ -363,10 +363,10 @@ checkType: } switch fieldType { - case orm.TypeBooleanField: - case orm.TypeVarCharField, orm.TypeCharField, orm.TypeJSONField, orm.TypeJsonbField: + case TypeBooleanField: + case TypeVarCharField, TypeCharField, TypeJSONField, TypeJsonbField: if size != "" { - v, e := orm.StrTo(size).Int32() + v, e := utils.StrTo(size).Int32() if e != nil { err = fmt.Errorf("wrong size value `%s`", size) } else { @@ -376,13 +376,13 @@ checkType: fi.Size = 255 fi.ToText = true } - case orm.TypeTextField: + case TypeTextField: fi.Index = false fi.Unique = false - case orm.TypeTimeField, orm.TypeDateField, orm.TypeDateTimeField: - if fieldType == orm.TypeDateTimeField { + case TypeTimeField, TypeDateField, TypeDateTimeField: + if fieldType == TypeDateTimeField { if precision != "" { - v, e := orm.StrTo(precision).Int() + v, e := utils.StrTo(precision).Int() if e != nil { err = fmt.Errorf("convert %s to int error:%v", precision, e) } else { @@ -396,12 +396,12 @@ checkType: } else if attrs["auto_now_add"] { fi.AutoNowAdd = true } - case orm.TypeFloatField: - case orm.TypeDecimalField: + case TypeFloatField: + case TypeDecimalField: d1 := digits d2 := decimals - v1, er1 := orm.StrTo(d1).Int8() - v2, er2 := orm.StrTo(d2).Int8() + v1, er1 := utils.StrTo(d1).Int8() + v2, er2 := utils.StrTo(d2).Int8() if er1 != nil || er2 != nil { err = fmt.Errorf("wrong digits/decimals value %s/%s", d2, d1) goto end @@ -410,12 +410,12 @@ checkType: fi.Decimals = int(v2) default: switch { - case fieldType&orm.IsIntegerField > 0: - case fieldType&orm.IsRelField > 0: + case fieldType&IsIntegerField > 0: + case fieldType&IsRelField > 0: } } - if fieldType&orm.IsIntegerField == 0 { + if fieldType&IsIntegerField == 0 { if fi.Auto { err = fmt.Errorf("non-integer type cannot set auto") goto end @@ -442,32 +442,32 @@ checkType: } // can not set default for these type - if fi.Auto || fi.Pk || fi.Unique || fieldType == orm.TypeTimeField || fieldType == orm.TypeDateField || fieldType == orm.TypeDateTimeField { + if fi.Auto || fi.Pk || fi.Unique || fieldType == TypeTimeField || fieldType == TypeDateField || fieldType == TypeDateTimeField { initial.Clear() } if initial.Exist() { v := initial switch fieldType { - case orm.TypeBooleanField: + case TypeBooleanField: _, err = v.Bool() - case orm.TypeFloatField, orm.TypeDecimalField: + case TypeFloatField, TypeDecimalField: _, err = v.Float64() - case orm.TypeBitField: + case TypeBitField: _, err = v.Int8() - case orm.TypeSmallIntegerField: + case TypeSmallIntegerField: _, err = v.Int16() - case orm.TypeIntegerField: + case TypeIntegerField: _, err = v.Int32() - case orm.TypeBigIntegerField: + case TypeBigIntegerField: _, err = v.Int64() - case orm.TypePositiveBitField: + case TypePositiveBitField: _, err = v.Uint8() - case orm.TypePositiveSmallIntegerField: + case TypePositiveSmallIntegerField: _, err = v.Uint16() - case orm.TypePositiveIntegerField: + case TypePositiveIntegerField: _, err = v.Uint32() - case orm.TypePositiveBigIntegerField: + case TypePositiveBigIntegerField: _, err = v.Uint64() } if err != nil { diff --git a/client/orm/internal/models/models_info_m.go b/client/orm/internal/models/models_info_m.go index 5d88b3d9..0dee0aa8 100644 --- a/client/orm/internal/models/models_info_m.go +++ b/client/orm/internal/models/models_info_m.go @@ -18,8 +18,6 @@ import ( "fmt" "os" "reflect" - - "github.com/beego/beego/v2/client/orm" ) // ModelInfo single model info @@ -113,7 +111,7 @@ func NewM2MModelInfo(m1, m2 *ModelInfo) (mi *ModelInfo) { fa := new(FieldInfo) // pk f1 := new(FieldInfo) // m1 table RelForeignKey f2 := new(FieldInfo) // m2 table RelForeignKey - fa.FieldType = orm.TypeBigIntegerField + fa.FieldType = TypeBigIntegerField fa.Auto = true fa.Pk = true fa.DBcol = true @@ -123,8 +121,8 @@ func NewM2MModelInfo(m1, m2 *ModelInfo) (mi *ModelInfo) { f1.DBcol = true f2.DBcol = true - f1.FieldType = orm.RelForeignKey - f2.FieldType = orm.RelForeignKey + f1.FieldType = RelForeignKey + f2.FieldType = RelForeignKey f1.Name = CamelString(m1.Table) f2.Name = CamelString(m2.Table) f1.FullName = mi.FullName + "." + f1.Name diff --git a/client/orm/internal/models/models_utils.go b/client/orm/internal/models/models_utils.go index 4b199e04..b5204606 100644 --- a/client/orm/internal/models/models_utils.go +++ b/client/orm/internal/models/models_utils.go @@ -21,7 +21,7 @@ import ( "strings" "time" - "github.com/beego/beego/v2/client/orm" + "github.com/beego/beego/v2/client/orm/internal/logs" ) // 1 is attr @@ -145,11 +145,11 @@ func getColumnName(ft int, addrField reflect.Value, sf reflect.StructField, col column = NameStrategyMap[NameStrategy](sf.Name) } switch ft { - case orm.RelForeignKey, orm.RelOneToOne: + case RelForeignKey, RelOneToOne: if len(col) == 0 { column = column + "_id" } - case orm.RelManyToMany, orm.RelReverseMany, orm.RelReverseOne: + case RelManyToMany, RelReverseMany, RelReverseOne: column = sf.Name } return column @@ -159,76 +159,76 @@ func getColumnName(ft int, addrField reflect.Value, sf reflect.StructField, col func getFieldType(val reflect.Value) (ft int, err error) { switch val.Type() { case reflect.TypeOf(new(int8)): - ft = orm.TypeBitField + ft = TypeBitField case reflect.TypeOf(new(int16)): - ft = orm.TypeSmallIntegerField + ft = TypeSmallIntegerField case reflect.TypeOf(new(int32)), reflect.TypeOf(new(int)): - ft = orm.TypeIntegerField + ft = TypeIntegerField case reflect.TypeOf(new(int64)): - ft = orm.TypeBigIntegerField + ft = TypeBigIntegerField case reflect.TypeOf(new(uint8)): - ft = orm.TypePositiveBitField + ft = TypePositiveBitField case reflect.TypeOf(new(uint16)): - ft = orm.TypePositiveSmallIntegerField + ft = TypePositiveSmallIntegerField case reflect.TypeOf(new(uint32)), reflect.TypeOf(new(uint)): - ft = orm.TypePositiveIntegerField + ft = TypePositiveIntegerField case reflect.TypeOf(new(uint64)): - ft = orm.TypePositiveBigIntegerField + ft = TypePositiveBigIntegerField case reflect.TypeOf(new(float32)), reflect.TypeOf(new(float64)): - ft = orm.TypeFloatField + ft = TypeFloatField case reflect.TypeOf(new(bool)): - ft = orm.TypeBooleanField + ft = TypeBooleanField case reflect.TypeOf(new(string)): - ft = orm.TypeVarCharField + ft = TypeVarCharField case reflect.TypeOf(new(time.Time)): - ft = orm.TypeDateTimeField + ft = TypeDateTimeField default: elm := reflect.Indirect(val) switch elm.Kind() { case reflect.Int8: - ft = orm.TypeBitField + ft = TypeBitField case reflect.Int16: - ft = orm.TypeSmallIntegerField + ft = TypeSmallIntegerField case reflect.Int32, reflect.Int: - ft = orm.TypeIntegerField + ft = TypeIntegerField case reflect.Int64: - ft = orm.TypeBigIntegerField + ft = TypeBigIntegerField case reflect.Uint8: - ft = orm.TypePositiveBitField + ft = TypePositiveBitField case reflect.Uint16: - ft = orm.TypePositiveSmallIntegerField + ft = TypePositiveSmallIntegerField case reflect.Uint32, reflect.Uint: - ft = orm.TypePositiveIntegerField + ft = TypePositiveIntegerField case reflect.Uint64: - ft = orm.TypePositiveBigIntegerField + ft = TypePositiveBigIntegerField case reflect.Float32, reflect.Float64: - ft = orm.TypeFloatField + ft = TypeFloatField case reflect.Bool: - ft = orm.TypeBooleanField + ft = TypeBooleanField case reflect.String: - ft = orm.TypeVarCharField + ft = TypeVarCharField default: if elm.Interface() == nil { panic(fmt.Errorf("%s is nil pointer, may be miss setting tag", val)) } switch elm.Interface().(type) { case sql.NullInt64: - ft = orm.TypeBigIntegerField + ft = TypeBigIntegerField case sql.NullFloat64: - ft = orm.TypeFloatField + ft = TypeFloatField case sql.NullBool: - ft = orm.TypeBooleanField + ft = TypeBooleanField case sql.NullString: - ft = orm.TypeVarCharField + ft = TypeVarCharField case time.Time: - ft = orm.TypeDateTimeField + ft = TypeDateTimeField } } } - if ft&orm.IsFieldType == 0 { + if ft&IsFieldType == 0 { err = fmt.Errorf("unsupport field type %s, may be miss setting tag", val) } return @@ -252,7 +252,7 @@ func ParseStructTag(data string) (attrs map[string]bool, tags map[string]string) tags[name] = v } } else { - orm.DebugLog.Println("unsupport orm tag", v) + logs.DebugLog.Println("unsupport orm tag", v) } } return diff --git a/client/orm/internal/models/types.go b/client/orm/internal/models/types.go new file mode 100644 index 00000000..f3b7989a --- /dev/null +++ b/client/orm/internal/models/types.go @@ -0,0 +1,23 @@ +// Copyright 2023 beego-dev. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package models + +// Fielder define field info +type Fielder interface { + String() string + FieldType() int + SetRaw(interface{}) error + RawValue() interface{} +} diff --git a/client/orm/internal/utils/utils.go b/client/orm/internal/utils/utils.go new file mode 100644 index 00000000..5e338487 --- /dev/null +++ b/client/orm/internal/utils/utils.go @@ -0,0 +1,249 @@ +// Copyright 2014 beego Author. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package utils + +import ( + "fmt" + "math/big" + "reflect" + "strconv" + "time" +) + +// StrTo is the target string +type StrTo string + +// Set string +func (f *StrTo) Set(v string) { + if v != "" { + *f = StrTo(v) + } else { + f.Clear() + } +} + +// Clear string +func (f *StrTo) Clear() { + *f = StrTo(rune(0x1E)) +} + +// Exist check string exist +func (f StrTo) Exist() bool { + return string(f) != string(rune(0x1E)) +} + +// Bool string to bool +func (f StrTo) Bool() (bool, error) { + return strconv.ParseBool(f.String()) +} + +// Float32 string to float32 +func (f StrTo) Float32() (float32, error) { + v, err := strconv.ParseFloat(f.String(), 32) + return float32(v), err +} + +// Float64 string to float64 +func (f StrTo) Float64() (float64, error) { + return strconv.ParseFloat(f.String(), 64) +} + +// Int string to int +func (f StrTo) Int() (int, error) { + v, err := strconv.ParseInt(f.String(), 10, 32) + return int(v), err +} + +// Int8 string to int8 +func (f StrTo) Int8() (int8, error) { + v, err := strconv.ParseInt(f.String(), 10, 8) + return int8(v), err +} + +// Int16 string to int16 +func (f StrTo) Int16() (int16, error) { + v, err := strconv.ParseInt(f.String(), 10, 16) + return int16(v), err +} + +// Int32 string to int32 +func (f StrTo) Int32() (int32, error) { + v, err := strconv.ParseInt(f.String(), 10, 32) + return int32(v), err +} + +// Int64 string to int64 +func (f StrTo) Int64() (int64, error) { + v, err := strconv.ParseInt(f.String(), 10, 64) + if err != nil { + i := new(big.Int) + ni, ok := i.SetString(f.String(), 10) // octal + if !ok { + return v, err + } + return ni.Int64(), nil + } + return v, err +} + +// Uint string to uint +func (f StrTo) Uint() (uint, error) { + v, err := strconv.ParseUint(f.String(), 10, 32) + return uint(v), err +} + +// Uint8 string to uint8 +func (f StrTo) Uint8() (uint8, error) { + v, err := strconv.ParseUint(f.String(), 10, 8) + return uint8(v), err +} + +// Uint16 string to uint16 +func (f StrTo) Uint16() (uint16, error) { + v, err := strconv.ParseUint(f.String(), 10, 16) + return uint16(v), err +} + +// Uint32 string to uint32 +func (f StrTo) Uint32() (uint32, error) { + v, err := strconv.ParseUint(f.String(), 10, 32) + return uint32(v), err +} + +// Uint64 string to uint64 +func (f StrTo) Uint64() (uint64, error) { + v, err := strconv.ParseUint(f.String(), 10, 64) + if err != nil { + i := new(big.Int) + ni, ok := i.SetString(f.String(), 10) + if !ok { + return v, err + } + return ni.Uint64(), nil + } + return v, err +} + +// String string to string +func (f StrTo) String() string { + if f.Exist() { + return string(f) + } + return "" +} + +// ToStr interface to string +func ToStr(value interface{}, args ...int) (s string) { + switch v := value.(type) { + case bool: + s = strconv.FormatBool(v) + case float32: + s = strconv.FormatFloat(float64(v), 'f', ArgInt(args).Get(0, -1), ArgInt(args).Get(1, 32)) + case float64: + s = strconv.FormatFloat(v, 'f', ArgInt(args).Get(0, -1), ArgInt(args).Get(1, 64)) + case int: + s = strconv.FormatInt(int64(v), ArgInt(args).Get(0, 10)) + case int8: + s = strconv.FormatInt(int64(v), ArgInt(args).Get(0, 10)) + case int16: + s = strconv.FormatInt(int64(v), ArgInt(args).Get(0, 10)) + case int32: + s = strconv.FormatInt(int64(v), ArgInt(args).Get(0, 10)) + case int64: + s = strconv.FormatInt(v, ArgInt(args).Get(0, 10)) + case uint: + s = strconv.FormatUint(uint64(v), ArgInt(args).Get(0, 10)) + case uint8: + s = strconv.FormatUint(uint64(v), ArgInt(args).Get(0, 10)) + case uint16: + s = strconv.FormatUint(uint64(v), ArgInt(args).Get(0, 10)) + case uint32: + s = strconv.FormatUint(uint64(v), ArgInt(args).Get(0, 10)) + case uint64: + s = strconv.FormatUint(v, ArgInt(args).Get(0, 10)) + case string: + s = v + case []byte: + s = string(v) + default: + s = fmt.Sprintf("%v", v) + } + return s +} + +// ToInt64 interface to int64 +func ToInt64(value interface{}) (d int64) { + val := reflect.ValueOf(value) + switch value.(type) { + case int, int8, int16, int32, int64: + d = val.Int() + case uint, uint8, uint16, uint32, uint64: + d = int64(val.Uint()) + default: + panic(fmt.Errorf("ToInt64 need numeric not `%T`", value)) + } + return +} + +type ArgString []string + +// Get get string by index from string slice +func (a ArgString) Get(i int, args ...string) (r string) { + if i >= 0 && i < len(a) { + r = a[i] + } else if len(args) > 0 { + r = args[0] + } + return +} + +type ArgInt []int + +// Get get int by index from int slice +func (a ArgInt) Get(i int, args ...int) (r int) { + if i >= 0 && i < len(a) { + r = a[i] + } + if len(args) > 0 { + r = args[0] + } + return +} + +// TimeParse parse time to string with location +func TimeParse(dateString, format string) (time.Time, error) { + tp, err := time.ParseInLocation(format, dateString, DefaultTimeLoc) + return tp, err +} + +// IndirectType get pointer indirect type +func IndirectType(v reflect.Type) reflect.Type { + switch v.Kind() { + case reflect.Ptr: + return IndirectType(v.Elem()) + default: + return v + } +} + +const ( + FormatTime = "15:04:05" + FormatDate = "2006-01-02" + FormatDateTime = "2006-01-02 15:04:05" +) + +var ( + DefaultTimeLoc = time.Local +) diff --git a/client/orm/models_fields.go b/client/orm/models_fields.go index b4fad94f..4f07ea18 100644 --- a/client/orm/models_fields.go +++ b/client/orm/models_fields.go @@ -15,91 +15,47 @@ package orm import ( - "fmt" - "strconv" - "time" + "github.com/beego/beego/v2/client/orm/internal/models" ) // Define the Type enum const ( - TypeBooleanField = 1 << iota - TypeVarCharField - TypeCharField - TypeTextField - TypeTimeField - TypeDateField - TypeDateTimeField - TypeBitField - TypeSmallIntegerField - TypeIntegerField - TypeBigIntegerField - TypePositiveBitField - TypePositiveSmallIntegerField - TypePositiveIntegerField - TypePositiveBigIntegerField - TypeFloatField - TypeDecimalField - TypeJSONField - TypeJsonbField - RelForeignKey - RelOneToOne - RelManyToMany - RelReverseOne - RelReverseMany + TypeBooleanField = models.TypeBooleanField + TypeVarCharField = models.TypeVarCharField + TypeCharField = models.TypeCharField + TypeTextField = models.TypeTextField + TypeTimeField = models.TypeTimeField + TypeDateField = models.TypeDateField + TypeDateTimeField = models.TypeDateTimeField + TypeBitField = models.TypeBitField + TypeSmallIntegerField = models.TypeSmallIntegerField + TypeIntegerField = models.TypeIntegerField + TypeBigIntegerField = models.TypeBigIntegerField + TypePositiveBitField = models.TypePositiveBitField + TypePositiveSmallIntegerField = models.TypePositiveSmallIntegerField + TypePositiveIntegerField = models.TypePositiveIntegerField + TypePositiveBigIntegerField = models.TypePositiveBigIntegerField + TypeFloatField = models.TypeFloatField + TypeDecimalField = models.TypeDecimalField + TypeJSONField = models.TypeJSONField + TypeJsonbField = models.TypeJsonbField + RelForeignKey = models.RelForeignKey + RelOneToOne = models.RelOneToOne + RelManyToMany = models.RelManyToMany + RelReverseOne = models.RelReverseOne + RelReverseMany = models.RelReverseMany ) // Define some logic enum const ( - IsIntegerField = ^-TypePositiveBigIntegerField >> 6 << 7 - IsPositiveIntegerField = ^-TypePositiveBigIntegerField >> 10 << 11 - IsRelField = ^-RelReverseMany >> 18 << 19 - IsFieldType = ^-RelReverseMany<<1 + 1 + IsIntegerField = models.IsIntegerField + IsPositiveIntegerField = models.IsPositiveIntegerField + IsRelField = models.IsRelField + IsFieldType = models.IsFieldType ) // BooleanField A true/false field. -type BooleanField bool - -// Value return the BooleanField -func (e BooleanField) Value() bool { - return bool(e) -} - -// Set will set the BooleanField -func (e *BooleanField) Set(d bool) { - *e = BooleanField(d) -} - -// String format the Bool to string -func (e *BooleanField) String() string { - return strconv.FormatBool(e.Value()) -} - -// FieldType return BooleanField the type -func (e *BooleanField) FieldType() int { - return TypeBooleanField -} - -// SetRaw set the interface to bool -func (e *BooleanField) SetRaw(value interface{}) error { - switch d := value.(type) { - case bool: - e.Set(d) - case string: - v, err := StrTo(d).Bool() - if err == nil { - e.Set(v) - } - return err - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return the current value -func (e *BooleanField) RawValue() interface{} { - return e.Value() -} +type BooleanField = models.BooleanField // verify the BooleanField implement the Fielder interface var _ Fielder = new(BooleanField) @@ -108,43 +64,7 @@ var _ Fielder = new(BooleanField) // required values tag: size // The size is enforced at the database level and in models’s validation. // eg: `orm:"size(120)"` -type CharField string - -// Value return the CharField's Value -func (e CharField) Value() string { - return string(e) -} - -// Set CharField value -func (e *CharField) Set(d string) { - *e = CharField(d) -} - -// String return the CharField -func (e *CharField) String() string { - return e.Value() -} - -// FieldType return the enum type -func (e *CharField) FieldType() int { - return TypeVarCharField -} - -// SetRaw set the interface to string -func (e *CharField) SetRaw(value interface{}) error { - switch d := value.(type) { - case string: - e.Set(d) - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return the CharField value -func (e *CharField) RawValue() interface{} { - return e.Value() -} +type CharField = models.CharField // verify CharField implement Fielder var _ Fielder = new(CharField) @@ -162,49 +82,7 @@ var _ Fielder = new(CharField) // Note that the current date is always used; it’s not just a default value that you can override. // // eg: `orm:"auto_now"` or `orm:"auto_now_add"` -type TimeField time.Time - -// Value return the time.Time -func (e TimeField) Value() time.Time { - return time.Time(e) -} - -// Set set the TimeField's value -func (e *TimeField) Set(d time.Time) { - *e = TimeField(d) -} - -// String convert time to string -func (e *TimeField) String() string { - return e.Value().String() -} - -// FieldType return enum type Date -func (e *TimeField) FieldType() int { - return TypeDateField -} - -// SetRaw convert the interface to time.Time. Allow string and time.Time -func (e *TimeField) SetRaw(value interface{}) error { - switch d := value.(type) { - case time.Time: - e.Set(d) - case string: - v, err := timeParse(d, formatTime) - if err == nil { - e.Set(v) - } - return err - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return time value -func (e *TimeField) RawValue() interface{} { - return e.Value() -} +type TimeField = models.TimeField var _ Fielder = new(TimeField) @@ -221,49 +99,7 @@ var _ Fielder = new(TimeField) // Note that the current date is always used; it’s not just a default value that you can override. // // eg: `orm:"auto_now"` or `orm:"auto_now_add"` -type DateField time.Time - -// Value return the time.Time -func (e DateField) Value() time.Time { - return time.Time(e) -} - -// Set set the DateField's value -func (e *DateField) Set(d time.Time) { - *e = DateField(d) -} - -// String convert datetime to string -func (e *DateField) String() string { - return e.Value().String() -} - -// FieldType return enum type Date -func (e *DateField) FieldType() int { - return TypeDateField -} - -// SetRaw convert the interface to time.Time. Allow string and time.Time -func (e *DateField) SetRaw(value interface{}) error { - switch d := value.(type) { - case time.Time: - e.Set(d) - case string: - v, err := timeParse(d, formatDate) - if err == nil { - e.Set(v) - } - return err - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return Date value -func (e *DateField) RawValue() interface{} { - return e.Value() -} +type DateField = models.DateField // verify DateField implement fielder interface var _ Fielder = new(DateField) @@ -271,513 +107,67 @@ var _ Fielder = new(DateField) // DateTimeField A date, represented in go by a time.Time instance. // datetime values like 2006-01-02 15:04:05 // Takes the same extra arguments as DateField. -type DateTimeField time.Time - -// Value return the datetime value -func (e DateTimeField) Value() time.Time { - return time.Time(e) -} - -// Set set the time.Time to datetime -func (e *DateTimeField) Set(d time.Time) { - *e = DateTimeField(d) -} - -// String return the time's String -func (e *DateTimeField) String() string { - return e.Value().String() -} - -// FieldType return the enum TypeDateTimeField -func (e *DateTimeField) FieldType() int { - return TypeDateTimeField -} - -// SetRaw convert the string or time.Time to DateTimeField -func (e *DateTimeField) SetRaw(value interface{}) error { - switch d := value.(type) { - case time.Time: - e.Set(d) - case string: - v, err := timeParse(d, formatDateTime) - if err == nil { - e.Set(v) - } - return err - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return the datetime value -func (e *DateTimeField) RawValue() interface{} { - return e.Value() -} +type DateTimeField = models.DateTimeField // verify datetime implement fielder -var _ Fielder = new(DateTimeField) +var _ models.Fielder = new(DateTimeField) // FloatField A floating-point number represented in go by a float32 value. -type FloatField float64 - -// Value return the FloatField value -func (e FloatField) Value() float64 { - return float64(e) -} - -// Set the Float64 -func (e *FloatField) Set(d float64) { - *e = FloatField(d) -} - -// String return the string -func (e *FloatField) String() string { - return ToStr(e.Value(), -1, 32) -} - -// FieldType return the enum type -func (e *FloatField) FieldType() int { - return TypeFloatField -} - -// SetRaw converter interface Float64 float32 or string to FloatField -func (e *FloatField) SetRaw(value interface{}) error { - switch d := value.(type) { - case float32: - e.Set(float64(d)) - case float64: - e.Set(d) - case string: - v, err := StrTo(d).Float64() - if err == nil { - e.Set(v) - } - return err - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return the FloatField value -func (e *FloatField) RawValue() interface{} { - return e.Value() -} +type FloatField = models.FloatField // verify FloatField implement Fielder var _ Fielder = new(FloatField) // SmallIntegerField -32768 to 32767 -type SmallIntegerField int16 - -// Value return int16 value -func (e SmallIntegerField) Value() int16 { - return int16(e) -} - -// Set the SmallIntegerField value -func (e *SmallIntegerField) Set(d int16) { - *e = SmallIntegerField(d) -} - -// String convert smallint to string -func (e *SmallIntegerField) String() string { - return ToStr(e.Value()) -} - -// FieldType return enum type SmallIntegerField -func (e *SmallIntegerField) FieldType() int { - return TypeSmallIntegerField -} - -// SetRaw convert interface int16/string to int16 -func (e *SmallIntegerField) SetRaw(value interface{}) error { - switch d := value.(type) { - case int16: - e.Set(d) - case string: - v, err := StrTo(d).Int16() - if err == nil { - e.Set(v) - } - return err - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return smallint value -func (e *SmallIntegerField) RawValue() interface{} { - return e.Value() -} +type SmallIntegerField = models.SmallIntegerField // verify SmallIntegerField implement Fielder var _ Fielder = new(SmallIntegerField) // IntegerField -2147483648 to 2147483647 -type IntegerField int32 - -// Value return the int32 -func (e IntegerField) Value() int32 { - return int32(e) -} - -// Set IntegerField value -func (e *IntegerField) Set(d int32) { - *e = IntegerField(d) -} - -// String convert Int32 to string -func (e *IntegerField) String() string { - return ToStr(e.Value()) -} - -// FieldType return the enum type -func (e *IntegerField) FieldType() int { - return TypeIntegerField -} - -// SetRaw convert interface int32/string to int32 -func (e *IntegerField) SetRaw(value interface{}) error { - switch d := value.(type) { - case int32: - e.Set(d) - case string: - v, err := StrTo(d).Int32() - if err == nil { - e.Set(v) - } - return err - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return IntegerField value -func (e *IntegerField) RawValue() interface{} { - return e.Value() -} +type IntegerField = models.IntegerField // verify IntegerField implement Fielder var _ Fielder = new(IntegerField) // BigIntegerField -9223372036854775808 to 9223372036854775807. -type BigIntegerField int64 - -// Value return int64 -func (e BigIntegerField) Value() int64 { - return int64(e) -} - -// Set the BigIntegerField value -func (e *BigIntegerField) Set(d int64) { - *e = BigIntegerField(d) -} - -// String convert BigIntegerField to string -func (e *BigIntegerField) String() string { - return ToStr(e.Value()) -} - -// FieldType return enum type -func (e *BigIntegerField) FieldType() int { - return TypeBigIntegerField -} - -// SetRaw convert interface int64/string to int64 -func (e *BigIntegerField) SetRaw(value interface{}) error { - switch d := value.(type) { - case int64: - e.Set(d) - case string: - v, err := StrTo(d).Int64() - if err == nil { - e.Set(v) - } - return err - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return BigIntegerField value -func (e *BigIntegerField) RawValue() interface{} { - return e.Value() -} +type BigIntegerField = models.BigIntegerField // verify BigIntegerField implement Fielder var _ Fielder = new(BigIntegerField) // PositiveSmallIntegerField 0 to 65535 -type PositiveSmallIntegerField uint16 - -// Value return uint16 -func (e PositiveSmallIntegerField) Value() uint16 { - return uint16(e) -} - -// Set PositiveSmallIntegerField value -func (e *PositiveSmallIntegerField) Set(d uint16) { - *e = PositiveSmallIntegerField(d) -} - -// String convert uint16 to string -func (e *PositiveSmallIntegerField) String() string { - return ToStr(e.Value()) -} - -// FieldType return enum type -func (e *PositiveSmallIntegerField) FieldType() int { - return TypePositiveSmallIntegerField -} - -// SetRaw convert Interface uint16/string to uint16 -func (e *PositiveSmallIntegerField) SetRaw(value interface{}) error { - switch d := value.(type) { - case uint16: - e.Set(d) - case string: - v, err := StrTo(d).Uint16() - if err == nil { - e.Set(v) - } - return err - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue returns PositiveSmallIntegerField value -func (e *PositiveSmallIntegerField) RawValue() interface{} { - return e.Value() -} +type PositiveSmallIntegerField = models.PositiveSmallIntegerField // verify PositiveSmallIntegerField implement Fielder var _ Fielder = new(PositiveSmallIntegerField) // PositiveIntegerField 0 to 4294967295 -type PositiveIntegerField uint32 - -// Value return PositiveIntegerField value. Uint32 -func (e PositiveIntegerField) Value() uint32 { - return uint32(e) -} - -// Set the PositiveIntegerField value -func (e *PositiveIntegerField) Set(d uint32) { - *e = PositiveIntegerField(d) -} - -// String convert PositiveIntegerField to string -func (e *PositiveIntegerField) String() string { - return ToStr(e.Value()) -} - -// FieldType return enum type -func (e *PositiveIntegerField) FieldType() int { - return TypePositiveIntegerField -} - -// SetRaw convert interface uint32/string to Uint32 -func (e *PositiveIntegerField) SetRaw(value interface{}) error { - switch d := value.(type) { - case uint32: - e.Set(d) - case string: - v, err := StrTo(d).Uint32() - if err == nil { - e.Set(v) - } - return err - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return the PositiveIntegerField Value -func (e *PositiveIntegerField) RawValue() interface{} { - return e.Value() -} +type PositiveIntegerField = models.PositiveIntegerField // verify PositiveIntegerField implement Fielder var _ Fielder = new(PositiveIntegerField) // PositiveBigIntegerField 0 to 18446744073709551615 -type PositiveBigIntegerField uint64 - -// Value return uint64 -func (e PositiveBigIntegerField) Value() uint64 { - return uint64(e) -} - -// Set PositiveBigIntegerField value -func (e *PositiveBigIntegerField) Set(d uint64) { - *e = PositiveBigIntegerField(d) -} - -// String convert PositiveBigIntegerField to string -func (e *PositiveBigIntegerField) String() string { - return ToStr(e.Value()) -} - -// FieldType return enum type -func (e *PositiveBigIntegerField) FieldType() int { - return TypePositiveIntegerField -} - -// SetRaw convert interface uint64/string to Uint64 -func (e *PositiveBigIntegerField) SetRaw(value interface{}) error { - switch d := value.(type) { - case uint64: - e.Set(d) - case string: - v, err := StrTo(d).Uint64() - if err == nil { - e.Set(v) - } - return err - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return PositiveBigIntegerField value -func (e *PositiveBigIntegerField) RawValue() interface{} { - return e.Value() -} +type PositiveBigIntegerField = models.PositiveBigIntegerField // verify PositiveBigIntegerField implement Fielder var _ Fielder = new(PositiveBigIntegerField) // TextField A large text field. -type TextField string - -// Value return TextField value -func (e TextField) Value() string { - return string(e) -} - -// Set the TextField value -func (e *TextField) Set(d string) { - *e = TextField(d) -} - -// String convert TextField to string -func (e *TextField) String() string { - return e.Value() -} - -// FieldType return enum type -func (e *TextField) FieldType() int { - return TypeTextField -} - -// SetRaw convert interface string to string -func (e *TextField) SetRaw(value interface{}) error { - switch d := value.(type) { - case string: - e.Set(d) - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return TextField value -func (e *TextField) RawValue() interface{} { - return e.Value() -} +type TextField = models.TextField // verify TextField implement Fielder var _ Fielder = new(TextField) // JSONField postgres json field. -type JSONField string - -// Value return JSONField value -func (j JSONField) Value() string { - return string(j) -} - -// Set the JSONField value -func (j *JSONField) Set(d string) { - *j = JSONField(d) -} - -// String convert JSONField to string -func (j *JSONField) String() string { - return j.Value() -} - -// FieldType return enum type -func (j *JSONField) FieldType() int { - return TypeJSONField -} - -// SetRaw convert interface string to string -func (j *JSONField) SetRaw(value interface{}) error { - switch d := value.(type) { - case string: - j.Set(d) - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return JSONField value -func (j *JSONField) RawValue() interface{} { - return j.Value() -} +type JSONField = models.JSONField // verify JSONField implement Fielder -var _ Fielder = new(JSONField) +var _ models.Fielder = new(JSONField) // JsonbField postgres json field. -type JsonbField string - -// Value return JsonbField value -func (j JsonbField) Value() string { - return string(j) -} - -// Set the JsonbField value -func (j *JsonbField) Set(d string) { - *j = JsonbField(d) -} - -// String convert JsonbField to string -func (j *JsonbField) String() string { - return j.Value() -} - -// FieldType return enum type -func (j *JsonbField) FieldType() int { - return TypeJsonbField -} - -// SetRaw convert interface string to string -func (j *JsonbField) SetRaw(value interface{}) error { - switch d := value.(type) { - case string: - j.Set(d) - default: - return fmt.Errorf(" unknown value `%s`", value) - } - return nil -} - -// RawValue return JsonbField value -func (j *JsonbField) RawValue() interface{} { - return j.Value() -} +type JsonbField = models.JsonbField // verify JsonbField implement Fielder -var _ Fielder = new(JsonbField) +var _ models.Fielder = new(JsonbField) diff --git a/client/orm/models_test.go b/client/orm/models_test.go index ea8a89fc..52bafd9e 100644 --- a/client/orm/models_test.go +++ b/client/orm/models_test.go @@ -22,6 +22,8 @@ import ( "strings" "time" + "github.com/beego/beego/v2/client/orm/internal/models" + _ "github.com/go-sql-driver/mysql" _ "github.com/lib/pq" _ "github.com/mattn/go-sqlite3" @@ -79,7 +81,7 @@ func (e *SliceStringField) RawValue() interface{} { return e.String() } -var _ Fielder = new(SliceStringField) +var _ models.Fielder = new(SliceStringField) // A json field. type JSONFieldTest struct { @@ -111,7 +113,7 @@ func (e *JSONFieldTest) RawValue() interface{} { return e.String() } -var _ Fielder = new(JSONFieldTest) +var _ models.Fielder = new(JSONFieldTest) type Data struct { ID int `orm:"column(id)"` diff --git a/client/orm/orm.go b/client/orm/orm.go index d9804e4a..bd84e6df 100644 --- a/client/orm/orm.go +++ b/client/orm/orm.go @@ -54,9 +54,10 @@ import ( "database/sql" "errors" "fmt" - "os" "reflect" - "time" + + ilogs "github.com/beego/beego/v2/client/orm/internal/logs" + iutils "github.com/beego/beego/v2/client/orm/internal/utils" "github.com/beego/beego/v2/client/orm/internal/models" @@ -74,10 +75,10 @@ const ( // Define common vars var ( Debug = false - DebugLog = NewLog(os.Stdout) + DebugLog = ilogs.DebugLog DefaultRowsLimit = -1 DefaultRelsDepth = 2 - DefaultTimeLoc = time.Local + DefaultTimeLoc = iutils.DefaultTimeLoc ErrTxDone = errors.New(" transaction already done") ErrMultiRows = errors.New(" return multi rows") ErrNoRows = errors.New(" no row found") @@ -479,7 +480,7 @@ func (o *ormBase) QueryTable(ptrStructOrTableName interface{}) (qs QuerySeter) { qs = newQuerySet(o, mi) } } else { - name = models.GetFullName(indirectType(reflect.TypeOf(ptrStructOrTableName))) + name = models.GetFullName(iutils.IndirectType(reflect.TypeOf(ptrStructOrTableName))) if mi, ok := defaultModelCache.getByFullName(name); ok { qs = newQuerySet(o, mi) } diff --git a/client/orm/orm_log.go b/client/orm/orm_log.go index e6f8bc83..50ebc3a6 100644 --- a/client/orm/orm_log.go +++ b/client/orm/orm_log.go @@ -22,23 +22,22 @@ import ( "log" "strings" "time" + + "github.com/beego/beego/v2/client/orm/internal/logs" ) -// Log implement the log.Logger -type Log struct { - *log.Logger -} - -// costomer log func -var LogFunc func(query map[string]interface{}) +type Log = logs.Log // NewLog set io.Writer to create a Logger. -func NewLog(out io.Writer) *Log { - d := new(Log) +func NewLog(out io.Writer) *logs.Log { + d := new(logs.Log) d.Logger = log.New(out, "[ORM]", log.LstdFlags) return d } +// LogFunc costomer log func +var LogFunc func(query map[string]interface{}) + func debugLogQueies(alias *alias, operaton, query string, t time.Time, err error, args ...interface{}) { logMap := make(map[string]interface{}) sub := time.Since(t) / 1e5 @@ -64,7 +63,7 @@ func debugLogQueies(alias *alias, operaton, query string, t time.Time, err error if LogFunc != nil { LogFunc(logMap) } - DebugLog.Println(con) + logs.DebugLog.Println(con) } // statement query logger struct. diff --git a/client/orm/orm_queryset.go b/client/orm/orm_queryset.go index d90ffbe5..8464741b 100644 --- a/client/orm/orm_queryset.go +++ b/client/orm/orm_queryset.go @@ -18,6 +18,8 @@ import ( "context" "fmt" + "github.com/beego/beego/v2/client/orm/internal/utils" + "github.com/beego/beego/v2/client/orm/internal/models" "github.com/beego/beego/v2/client/orm/clauses/order_clause" @@ -56,7 +58,7 @@ func ColValue(opt operator, value interface{}) interface{} { default: panic(fmt.Errorf("orm.ColValue wrong operator")) } - v, err := StrTo(ToStr(value)).Int64() + v, err := utils.StrTo(utils.ToStr(value)).Int64() if err != nil { panic(fmt.Errorf("orm.ColValue doesn't support non string/numeric type, %s", err)) } @@ -115,13 +117,13 @@ func (o querySet) Exclude(expr string, args ...interface{}) QuerySeter { // set offset number func (o *querySet) setOffset(num interface{}) { - o.offset = ToInt64(num) + o.offset = utils.ToInt64(num) } // add LIMIT value. // args[0] means offset, e.g. LIMIT num,offset. func (o querySet) Limit(limit interface{}, args ...interface{}) QuerySeter { - o.limit = ToInt64(limit) + o.limit = utils.ToInt64(limit) if len(args) > 0 { o.setOffset(args[0]) } diff --git a/client/orm/orm_raw.go b/client/orm/orm_raw.go index 78929a2d..d1b1d0a7 100644 --- a/client/orm/orm_raw.go +++ b/client/orm/orm_raw.go @@ -20,6 +20,8 @@ import ( "reflect" "time" + "github.com/beego/beego/v2/client/orm/internal/utils" + "github.com/beego/beego/v2/client/orm/internal/models" "github.com/pkg/errors" @@ -97,7 +99,7 @@ func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { } else if v, ok := value.(bool); ok { ind.SetBool(v) } else { - v, _ := StrTo(ToStr(value)).Bool() + v, _ := utils.StrTo(utils.ToStr(value)).Bool() ind.SetBool(v) } @@ -105,7 +107,7 @@ func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { if value == nil { ind.SetString("") } else { - ind.SetString(ToStr(value)) + ind.SetString(utils.ToStr(value)) } case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: @@ -119,7 +121,7 @@ func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: ind.SetInt(int64(val.Uint())) default: - v, _ := StrTo(ToStr(value)).Int64() + v, _ := utils.StrTo(utils.ToStr(value)).Int64() ind.SetInt(v) } } @@ -134,7 +136,7 @@ func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: ind.SetUint(val.Uint()) default: - v, _ := StrTo(ToStr(value)).Uint64() + v, _ := utils.StrTo(utils.ToStr(value)).Uint64() ind.SetUint(v) } } @@ -147,7 +149,7 @@ func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { case reflect.Float64: ind.SetFloat(val.Float()) default: - v, _ := StrTo(ToStr(value)).Float64() + v, _ := utils.StrTo(utils.ToStr(value)).Float64() ind.SetFloat(v) } } @@ -172,20 +174,20 @@ func (o *rawSet) setFieldValue(ind reflect.Value, value interface{}) { if str != "" { if len(str) >= 19 { str = str[:19] - t, err := time.ParseInLocation(formatDateTime, str, o.orm.alias.TZ) + t, err := time.ParseInLocation(utils.FormatDateTime, str, o.orm.alias.TZ) if err == nil { t = t.In(DefaultTimeLoc) ind.Set(reflect.ValueOf(t)) } } else if len(str) >= 10 { str = str[:10] - t, err := time.ParseInLocation(formatDate, str, DefaultTimeLoc) + t, err := time.ParseInLocation(utils.FormatDate, str, DefaultTimeLoc) if err == nil { ind.Set(reflect.ValueOf(t)) } } else if len(str) >= 8 { str = str[:8] - t, err := time.ParseInLocation(formatTime, str, DefaultTimeLoc) + t, err := time.ParseInLocation(utils.FormatTime, str, DefaultTimeLoc) if err == nil { ind.Set(reflect.ValueOf(t)) } @@ -381,7 +383,7 @@ func (o *rawSet) QueryRow(containers ...interface{}) error { field = mf.Elem().FieldByIndex(fi.RelModelInfo.Fields.Pk.FieldIndex) } if fi.IsFielder { - fd := field.Addr().Interface().(Fielder) + fd := field.Addr().Interface().(models.Fielder) err := fd.SetRaw(value) if err != nil { return errors.Errorf("set raw error:%s", err) @@ -548,7 +550,7 @@ func (o *rawSet) QueryRows(containers ...interface{}) (int64, error) { field = mf.Elem().FieldByIndex(fi.RelModelInfo.Fields.Pk.FieldIndex) } if fi.IsFielder { - fd := field.Addr().Interface().(Fielder) + fd := field.Addr().Interface().(models.Fielder) err := fd.SetRaw(value) if err != nil { return 0, errors.Errorf("set raw error:%s", err) diff --git a/client/orm/orm_test.go b/client/orm/orm_test.go index e4e928a0..0c31e085 100644 --- a/client/orm/orm_test.go +++ b/client/orm/orm_test.go @@ -29,6 +29,10 @@ import ( "testing" "time" + "github.com/beego/beego/v2/client/orm/internal/logs" + + "github.com/beego/beego/v2/client/orm/internal/utils" + "github.com/beego/beego/v2/client/orm/internal/models" "github.com/stretchr/testify/assert" @@ -40,9 +44,9 @@ import ( var _ = os.PathSeparator var ( - testDate = formatDate + " -0700" - testDateTime = formatDateTime + " -0700" - testTime = formatTime + " -0700" + testDate = utils.FormatDate + " -0700" + testDateTime = utils.FormatDateTime + " -0700" + testTime = utils.FormatTime + " -0700" ) type argAny []interface{} @@ -71,7 +75,7 @@ func ValuesCompare(is bool, a interface{}, args ...interface{}) (ok bool, err er case time.Time: if v2, vo := b.(time.Time); vo { if arg.Get(1) != nil { - format := ToStr(arg.Get(1)) + format := utils.ToStr(arg.Get(1)) a = v.Format(format) b = v2.Format(format) ok = a == b @@ -81,7 +85,7 @@ func ValuesCompare(is bool, a interface{}, args ...interface{}) (ok bool, err er } } default: - ok = ToStr(a) == ToStr(b) + ok = utils.ToStr(a) == utils.ToStr(b) } ok = is && ok || !is && !ok if !ok { @@ -2933,9 +2937,9 @@ func TestDebugLog(t *testing.T) { func captureDebugLogOutput(f func()) string { var buf bytes.Buffer - DebugLog.SetOutput(&buf) + logs.DebugLog.SetOutput(&buf) defer func() { - DebugLog.SetOutput(os.Stderr) + logs.DebugLog.SetOutput(os.Stderr) }() f() return buf.String() diff --git a/client/orm/types.go b/client/orm/types.go index 76ce2a8d..649d29fc 100644 --- a/client/orm/types.go +++ b/client/orm/types.go @@ -97,13 +97,7 @@ type Driver interface { Type() DriverType } -// Fielder define field info -type Fielder interface { - String() string - FieldType() int - SetRaw(interface{}) error - RawValue() interface{} -} +type Fielder = models.Fielder type TxBeginner interface { // Begin self control transaction diff --git a/client/orm/utils.go b/client/orm/utils.go index def4f8c9..40a818d6 100644 --- a/client/orm/utils.go +++ b/client/orm/utils.go @@ -15,235 +15,15 @@ package orm import ( - "fmt" - "math/big" - "reflect" - "strconv" - "time" - "github.com/beego/beego/v2/client/orm/internal/models" + "github.com/beego/beego/v2/client/orm/internal/utils" ) -// StrTo is the target string -type StrTo string +type StrTo = utils.StrTo -// Set string -func (f *StrTo) Set(v string) { - if v != "" { - *f = StrTo(v) - } else { - f.Clear() - } -} - -// Clear string -func (f *StrTo) Clear() { - *f = StrTo(rune(0x1E)) -} - -// Exist check string exist -func (f StrTo) Exist() bool { - return string(f) != string(rune(0x1E)) -} - -// Bool string to bool -func (f StrTo) Bool() (bool, error) { - return strconv.ParseBool(f.String()) -} - -// Float32 string to float32 -func (f StrTo) Float32() (float32, error) { - v, err := strconv.ParseFloat(f.String(), 32) - return float32(v), err -} - -// Float64 string to float64 -func (f StrTo) Float64() (float64, error) { - return strconv.ParseFloat(f.String(), 64) -} - -// Int string to int -func (f StrTo) Int() (int, error) { - v, err := strconv.ParseInt(f.String(), 10, 32) - return int(v), err -} - -// Int8 string to int8 -func (f StrTo) Int8() (int8, error) { - v, err := strconv.ParseInt(f.String(), 10, 8) - return int8(v), err -} - -// Int16 string to int16 -func (f StrTo) Int16() (int16, error) { - v, err := strconv.ParseInt(f.String(), 10, 16) - return int16(v), err -} - -// Int32 string to int32 -func (f StrTo) Int32() (int32, error) { - v, err := strconv.ParseInt(f.String(), 10, 32) - return int32(v), err -} - -// Int64 string to int64 -func (f StrTo) Int64() (int64, error) { - v, err := strconv.ParseInt(f.String(), 10, 64) - if err != nil { - i := new(big.Int) - ni, ok := i.SetString(f.String(), 10) // octal - if !ok { - return v, err - } - return ni.Int64(), nil - } - return v, err -} - -// Uint string to uint -func (f StrTo) Uint() (uint, error) { - v, err := strconv.ParseUint(f.String(), 10, 32) - return uint(v), err -} - -// Uint8 string to uint8 -func (f StrTo) Uint8() (uint8, error) { - v, err := strconv.ParseUint(f.String(), 10, 8) - return uint8(v), err -} - -// Uint16 string to uint16 -func (f StrTo) Uint16() (uint16, error) { - v, err := strconv.ParseUint(f.String(), 10, 16) - return uint16(v), err -} - -// Uint32 string to uint32 -func (f StrTo) Uint32() (uint32, error) { - v, err := strconv.ParseUint(f.String(), 10, 32) - return uint32(v), err -} - -// Uint64 string to uint64 -func (f StrTo) Uint64() (uint64, error) { - v, err := strconv.ParseUint(f.String(), 10, 64) - if err != nil { - i := new(big.Int) - ni, ok := i.SetString(f.String(), 10) - if !ok { - return v, err - } - return ni.Uint64(), nil - } - return v, err -} - -// String string to string -func (f StrTo) String() string { - if f.Exist() { - return string(f) - } - return "" -} - -// ToStr interface to string -func ToStr(value interface{}, args ...int) (s string) { - switch v := value.(type) { - case bool: - s = strconv.FormatBool(v) - case float32: - s = strconv.FormatFloat(float64(v), 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 32)) - case float64: - s = strconv.FormatFloat(v, 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 64)) - case int: - s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10)) - case int8: - s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10)) - case int16: - s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10)) - case int32: - s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10)) - case int64: - s = strconv.FormatInt(v, argInt(args).Get(0, 10)) - case uint: - s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10)) - case uint8: - s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10)) - case uint16: - s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10)) - case uint32: - s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10)) - case uint64: - s = strconv.FormatUint(v, argInt(args).Get(0, 10)) - case string: - s = v - case []byte: - s = string(v) - default: - s = fmt.Sprintf("%v", v) - } - return s -} - -// ToInt64 interface to int64 -func ToInt64(value interface{}) (d int64) { - val := reflect.ValueOf(value) - switch value.(type) { - case int, int8, int16, int32, int64: - d = val.Int() - case uint, uint8, uint16, uint32, uint64: - d = int64(val.Uint()) - default: - panic(fmt.Errorf("ToInt64 need numeric not `%T`", value)) - } - return -} - -// SetNameStrategy set different name strategy func SetNameStrategy(s string) { if models.SnakeAcronymNameStrategy != s { models.NameStrategy = models.DefaultNameStrategy } models.NameStrategy = s } - -type argString []string - -// Get get string by index from string slice -func (a argString) Get(i int, args ...string) (r string) { - if i >= 0 && i < len(a) { - r = a[i] - } else if len(args) > 0 { - r = args[0] - } - return -} - -type argInt []int - -// get int by index from int slice -func (a argInt) Get(i int, args ...int) (r int) { - if i >= 0 && i < len(a) { - r = a[i] - } - if len(args) > 0 { - r = args[0] - } - return -} - -// parse time to string with location -func timeParse(dateString, format string) (time.Time, error) { - tp, err := time.ParseInLocation(format, dateString, DefaultTimeLoc) - return tp, err -} - -// get pointer indirect type -func indirectType(v reflect.Type) reflect.Type { - switch v.Kind() { - case reflect.Ptr: - return indirectType(v.Elem()) - default: - return v - } -}