Add double FIELD TYPE and improve type checking
This commit is contained in:
parent
543e864ed8
commit
4c8d5213dc
4 changed files with 101 additions and 24 deletions
|
@ -1413,11 +1413,11 @@ func Test_Parse_Queries_Define(t *testing.T) {
|
|||
},
|
||||
{
|
||||
sql: `DEFINE FIELD temp ON person TYPE`,
|
||||
err: "Found `` but expected `any, url, uuid, color, email, phone, array, object, domain, string, number, custom, boolean, datetime, latitude, longitude`",
|
||||
err: "Found `` but expected `any, url, uuid, color, email, phone, array, object, domain, string, number, double, custom, boolean, datetime, latitude, longitude`",
|
||||
},
|
||||
{
|
||||
sql: `DEFINE FIELD temp ON person TYPE something`,
|
||||
err: "Found `something` but expected `any, url, uuid, color, email, phone, array, object, domain, string, number, custom, boolean, datetime, latitude, longitude`",
|
||||
err: "Found `something` but expected `any, url, uuid, color, email, phone, array, object, domain, string, number, double, custom, boolean, datetime, latitude, longitude`",
|
||||
},
|
||||
{
|
||||
sql: `DEFINE FIELD temp ON person TYPE any`,
|
||||
|
@ -1483,6 +1483,14 @@ func Test_Parse_Queries_Define(t *testing.T) {
|
|||
Type: "number",
|
||||
}}},
|
||||
},
|
||||
{
|
||||
sql: `DEFINE FIELD temp ON person TYPE double`,
|
||||
res: &Query{Statements: []Statement{&DefineFieldStatement{
|
||||
Name: "temp",
|
||||
What: []string{"person"},
|
||||
Type: "double",
|
||||
}}},
|
||||
},
|
||||
{
|
||||
sql: `DEFINE FIELD temp ON person TYPE custom`,
|
||||
res: &Query{Statements: []Statement{&DefineFieldStatement{
|
||||
|
|
|
@ -16,7 +16,7 @@ package sql
|
|||
|
||||
func (p *parser) parseType() (exp string, err error) {
|
||||
|
||||
allowed := []string{"any", "url", "uuid", "color", "email", "phone", "array", "object", "domain", "string", "number", "custom", "boolean", "datetime", "latitude", "longitude"}
|
||||
allowed := []string{"any", "url", "uuid", "color", "email", "phone", "array", "object", "domain", "string", "number", "double", "custom", "boolean", "datetime", "latitude", "longitude"}
|
||||
|
||||
_, lit, err := p.shouldBe(IDENT, CUSTOM)
|
||||
if err != nil {
|
||||
|
|
|
@ -16,13 +16,40 @@ package conv
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/asaskevich/govalidator"
|
||||
)
|
||||
|
||||
func toNumber(str string) (int64, error) {
|
||||
val, err := strconv.ParseFloat(str, 64)
|
||||
if err != nil {
|
||||
val = 0.0
|
||||
}
|
||||
return int64(val), err
|
||||
}
|
||||
|
||||
func toDouble(str string) (float64, error) {
|
||||
val, err := strconv.ParseFloat(str, 64)
|
||||
if err != nil {
|
||||
val = 0.0
|
||||
}
|
||||
return float64(val), err
|
||||
}
|
||||
|
||||
func toBoolean(str string) (bool, error) {
|
||||
val, err := strconv.ParseBool(str)
|
||||
if err != nil {
|
||||
val = false
|
||||
}
|
||||
return bool(val), err
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
|
||||
func ConvertToUrl(obj interface{}) (val string, err error) {
|
||||
val = govalidator.ToString(obj)
|
||||
val = fmt.Sprintf("%v", obj)
|
||||
if !govalidator.IsURL(val) {
|
||||
err = fmt.Errorf("Not a valid url")
|
||||
}
|
||||
|
@ -30,7 +57,7 @@ func ConvertToUrl(obj interface{}) (val string, err error) {
|
|||
}
|
||||
|
||||
func ConvertToUuid(obj interface{}) (val string, err error) {
|
||||
val = govalidator.ToString(obj)
|
||||
val = fmt.Sprintf("%v", obj)
|
||||
if !govalidator.IsUUID(val) {
|
||||
err = fmt.Errorf("Not a valid uuid")
|
||||
}
|
||||
|
@ -38,7 +65,7 @@ func ConvertToUuid(obj interface{}) (val string, err error) {
|
|||
}
|
||||
|
||||
func ConvertToEmail(obj interface{}) (val string, err error) {
|
||||
val = govalidator.ToString(obj)
|
||||
val = fmt.Sprintf("%v", obj)
|
||||
if !govalidator.IsEmail(val) {
|
||||
err = fmt.Errorf("Not a valid email")
|
||||
}
|
||||
|
@ -46,7 +73,7 @@ func ConvertToEmail(obj interface{}) (val string, err error) {
|
|||
}
|
||||
|
||||
func ConvertToPhone(obj interface{}) (val string, err error) {
|
||||
val = govalidator.ToString(obj)
|
||||
val = fmt.Sprintf("%v", obj)
|
||||
if !govalidator.Matches(val, `^[\s\d\+\-\(\)]+$`) {
|
||||
err = fmt.Errorf("Not a valid phone")
|
||||
}
|
||||
|
@ -54,7 +81,7 @@ func ConvertToPhone(obj interface{}) (val string, err error) {
|
|||
}
|
||||
|
||||
func ConvertToColor(obj interface{}) (val string, err error) {
|
||||
val = govalidator.ToString(obj)
|
||||
val = fmt.Sprintf("%v", obj)
|
||||
if !govalidator.IsHexcolor(val) && !govalidator.IsRGBcolor(val) {
|
||||
err = fmt.Errorf("Not a valid color")
|
||||
}
|
||||
|
@ -80,7 +107,7 @@ func ConvertToObject(obj interface{}) (val map[string]interface{}, err error) {
|
|||
}
|
||||
|
||||
func ConvertToDomain(obj interface{}) (val string, err error) {
|
||||
val = govalidator.ToString(obj)
|
||||
val = fmt.Sprintf("%v", obj)
|
||||
if !govalidator.IsDNSName(val) {
|
||||
err = fmt.Errorf("Not a valid domain name")
|
||||
}
|
||||
|
@ -88,7 +115,7 @@ func ConvertToDomain(obj interface{}) (val string, err error) {
|
|||
}
|
||||
|
||||
func ConvertToBase64(obj interface{}) (val string, err error) {
|
||||
val = govalidator.ToString(obj)
|
||||
val = fmt.Sprintf("%v", obj)
|
||||
if !govalidator.IsBase64(val) {
|
||||
err = fmt.Errorf("Not valid base64 data")
|
||||
}
|
||||
|
@ -96,24 +123,55 @@ func ConvertToBase64(obj interface{}) (val string, err error) {
|
|||
}
|
||||
|
||||
func ConvertToString(obj interface{}) (val string, err error) {
|
||||
if now, ok := obj.(string); ok {
|
||||
switch now := obj.(type) {
|
||||
case string:
|
||||
return now, err
|
||||
case []interface{}:
|
||||
return val, fmt.Errorf("Not valid string")
|
||||
case map[string]interface{}:
|
||||
return val, fmt.Errorf("Not valid string")
|
||||
default:
|
||||
return fmt.Sprintf("%v", obj), err
|
||||
}
|
||||
return govalidator.ToString(obj), err
|
||||
}
|
||||
|
||||
func ConvertToNumber(obj interface{}) (val float64, err error) {
|
||||
if now, ok := obj.(float64); ok {
|
||||
return now, err
|
||||
func ConvertToNumber(obj interface{}) (val int64, err error) {
|
||||
switch now := obj.(type) {
|
||||
case int64:
|
||||
return int64(now), err
|
||||
case float64:
|
||||
return int64(now), err
|
||||
case string:
|
||||
return toNumber(now)
|
||||
default:
|
||||
return toNumber(fmt.Sprintf("%v", obj))
|
||||
}
|
||||
}
|
||||
|
||||
func ConvertToDouble(obj interface{}) (val float64, err error) {
|
||||
switch now := obj.(type) {
|
||||
case int64:
|
||||
return float64(now), err
|
||||
case float64:
|
||||
return float64(now), err
|
||||
case string:
|
||||
return toDouble(now)
|
||||
default:
|
||||
return toDouble(fmt.Sprintf("%v", obj))
|
||||
}
|
||||
return govalidator.ToFloat(govalidator.ToString(obj))
|
||||
}
|
||||
|
||||
func ConvertToBoolean(obj interface{}) (val bool, err error) {
|
||||
if now, ok := obj.(bool); ok {
|
||||
return now, err
|
||||
switch now := obj.(type) {
|
||||
case int64:
|
||||
return now > 0, err
|
||||
case float64:
|
||||
return now > 0, err
|
||||
case string:
|
||||
return toBoolean(now)
|
||||
default:
|
||||
return toBoolean(fmt.Sprintf("%v", obj))
|
||||
}
|
||||
return govalidator.ToBoolean(govalidator.ToString(obj))
|
||||
}
|
||||
|
||||
func ConvertToDatetime(obj interface{}) (val time.Time, err error) {
|
||||
|
@ -126,7 +184,7 @@ func ConvertToDatetime(obj interface{}) (val time.Time, err error) {
|
|||
}
|
||||
|
||||
func ConvertToLatitude(obj interface{}) (val float64, err error) {
|
||||
str := govalidator.ToString(obj)
|
||||
str := fmt.Sprintf("%v", obj)
|
||||
if !govalidator.IsLatitude(str) {
|
||||
err = fmt.Errorf("Not a valid latitude")
|
||||
}
|
||||
|
@ -134,8 +192,8 @@ func ConvertToLatitude(obj interface{}) (val float64, err error) {
|
|||
}
|
||||
|
||||
func ConvertToLongitude(obj interface{}) (val float64, err error) {
|
||||
str := govalidator.ToString(obj)
|
||||
if !govalidator.IsLatitude(str) {
|
||||
str := fmt.Sprintf("%v", obj)
|
||||
if !govalidator.IsLongitude(str) {
|
||||
err = fmt.Errorf("Not a valid longitude")
|
||||
}
|
||||
return govalidator.ToFloat(str)
|
||||
|
@ -145,10 +203,10 @@ func ConvertToOneOf(obj interface{}, pos ...interface{}) (val interface{}, err e
|
|||
for _, now := range pos {
|
||||
if num, ok := obj.(int64); ok {
|
||||
if float64(num) == now {
|
||||
return obj, nil
|
||||
return obj, err
|
||||
}
|
||||
} else if obj == now {
|
||||
return obj, nil
|
||||
return obj, err
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("Not a valid option")
|
||||
|
|
|
@ -237,6 +237,17 @@ func each(fld *sql.DefineFieldStatement, initial *data.Doc, current *data.Doc) (
|
|||
}
|
||||
}
|
||||
|
||||
case "double":
|
||||
if val, err := conv.ConvertToDouble(c); err == nil {
|
||||
current.Set(val, fld.Name)
|
||||
} else {
|
||||
if fld.Validate {
|
||||
return fmt.Errorf("Field '%v' needs to be a double", fld.Name)
|
||||
} else {
|
||||
current.Iff(i, fld.Name)
|
||||
}
|
||||
}
|
||||
|
||||
case "boolean":
|
||||
if val, err := conv.ConvertToBoolean(c); err == nil {
|
||||
current.Set(val, fld.Name)
|
||||
|
|
Loading…
Reference in a new issue