Merge branch 'develop' of github.com:beego/beego into develop

This commit is contained in:
Deng Ming 2023-06-08 23:06:22 +08:00
commit 34c5f1d54d
27 changed files with 1327 additions and 1324 deletions

View File

@ -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)

View File

@ -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)
}
}

View File

@ -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" {

View File

@ -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 ``
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 ``
}

View File

@ -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 ``
}
}

View File

@ -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()

View File

@ -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
}

View File

@ -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
}

View File

@ -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("<BooleanField.SetRaw> 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 modelss 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("<CharField.SetRaw> 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; its 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; its 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("<TimeField.SetRaw> 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; its 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; its 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("<DateField.SetRaw> 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("<DateTimeField.SetRaw> 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("<FloatField.SetRaw> 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("<SmallIntegerField.SetRaw> 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("<IntegerField.SetRaw> 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("<BigIntegerField.SetRaw> 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("<PositiveSmallIntegerField.SetRaw> 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("<PositiveIntegerField.SetRaw> 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("<PositiveBigIntegerField.SetRaw> 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("<TextField.SetRaw> 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("<JSONField.SetRaw> 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("<JsonbField.SetRaw> 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)

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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{}
}

View File

@ -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
)

View File

@ -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("<BooleanField.SetRaw> 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 modelss 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("<CharField.SetRaw> 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; its 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("<TimeField.SetRaw> 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; its 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("<DateField.SetRaw> 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("<DateTimeField.SetRaw> 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("<FloatField.SetRaw> 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("<SmallIntegerField.SetRaw> 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("<IntegerField.SetRaw> 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("<BigIntegerField.SetRaw> 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("<PositiveSmallIntegerField.SetRaw> 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("<PositiveIntegerField.SetRaw> 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("<PositiveBigIntegerField.SetRaw> 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("<TextField.SetRaw> 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("<JSONField.SetRaw> 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("<JsonbField.SetRaw> 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)

View File

@ -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)"`

View File

@ -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("<TxOrmer.Commit/Rollback> transaction already done")
ErrMultiRows = errors.New("<QuerySeter> return multi rows")
ErrNoRows = errors.New("<QuerySeter> 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)
}

View File

@ -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.

View File

@ -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])
}

View File

@ -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)

View File

@ -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()

View File

@ -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

View File

@ -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
}
}