Simplify built-in database field types
This commit is contained in:
parent
e52f0d3243
commit
26b138b9b0
14 changed files with 329 additions and 236 deletions
13
glide.lock
generated
13
glide.lock
generated
|
@ -1,8 +1,8 @@
|
||||||
hash: 7227d566f4817cbb8b1eb609aeb5928f1bc420f763fbf387d5effcfa2e8e6509
|
hash: bb2fdd0ae1ce4cc20cd04c5fb3720722f46051ec869b6e61e21d9b8e7f020081
|
||||||
updated: 2018-09-11T13:25:49.903968+01:00
|
updated: 2018-10-17T23:52:04.807878+01:00
|
||||||
imports:
|
imports:
|
||||||
- name: cloud.google.com/go
|
- name: cloud.google.com/go
|
||||||
version: c728a003b238b26cef9ab6753a5dc424b331c3ad
|
version: dfffe386c33fb24c34ee501e5723df5b97b98514
|
||||||
subpackages:
|
subpackages:
|
||||||
- compute/metadata
|
- compute/metadata
|
||||||
- iam
|
- iam
|
||||||
|
@ -39,7 +39,7 @@ imports:
|
||||||
- name: github.com/armon/go-metrics
|
- name: github.com/armon/go-metrics
|
||||||
version: 3c58d8115a78a6879e5df75ae900846768d36895
|
version: 3c58d8115a78a6879e5df75ae900846768d36895
|
||||||
- name: github.com/aws/aws-sdk-go
|
- name: github.com/aws/aws-sdk-go
|
||||||
version: 71a2a92b0063297b055b6f5a014d441c142da2ce
|
version: 66832f7f150914a46ffbfc03210f3b9cb0e4c005
|
||||||
subpackages:
|
subpackages:
|
||||||
- aws
|
- aws
|
||||||
- aws/awserr
|
- aws/awserr
|
||||||
|
@ -58,6 +58,7 @@ imports:
|
||||||
- aws/request
|
- aws/request
|
||||||
- aws/session
|
- aws/session
|
||||||
- aws/signer/v4
|
- aws/signer/v4
|
||||||
|
- internal/s3err
|
||||||
- internal/sdkio
|
- internal/sdkio
|
||||||
- internal/sdkrand
|
- internal/sdkrand
|
||||||
- internal/sdkuri
|
- internal/sdkuri
|
||||||
|
@ -139,6 +140,8 @@ imports:
|
||||||
version: 80517062f582ea3340cd4baf70e86d539ae7d84d
|
version: 80517062f582ea3340cd4baf70e86d539ae7d84d
|
||||||
subpackages:
|
subpackages:
|
||||||
- internal/load
|
- internal/load
|
||||||
|
- name: github.com/konsorten/go-windows-terminal-sequences
|
||||||
|
version: 5c8c8bd35d3832f5d134ae1e1e375b69a4d25242
|
||||||
- name: github.com/kr/text
|
- name: github.com/kr/text
|
||||||
version: e2ffdb16a802fe2bb95e2e35ff34f0e53aeef34f
|
version: e2ffdb16a802fe2bb95e2e35ff34f0e53aeef34f
|
||||||
- name: github.com/mattn/go-colorable
|
- name: github.com/mattn/go-colorable
|
||||||
|
@ -175,7 +178,7 @@ imports:
|
||||||
subpackages:
|
subpackages:
|
||||||
- diffmatchpatch
|
- diffmatchpatch
|
||||||
- name: github.com/sirupsen/logrus
|
- name: github.com/sirupsen/logrus
|
||||||
version: 3e01752db0189b9157070a0e1668a620f9a85da2
|
version: ad15b42461921f1fb3529b058c6786c6a45d5162
|
||||||
- name: github.com/spf13/cobra
|
- name: github.com/spf13/cobra
|
||||||
version: ef82de70bb3f60c65fb8eebacbb2d122ef517385
|
version: ef82de70bb3f60c65fb8eebacbb2d122ef517385
|
||||||
- name: github.com/spf13/pflag
|
- name: github.com/spf13/pflag
|
||||||
|
|
|
@ -33,7 +33,7 @@ import:
|
||||||
subpackages:
|
subpackages:
|
||||||
- diffmatchpatch
|
- diffmatchpatch
|
||||||
- package: github.com/sirupsen/logrus
|
- package: github.com/sirupsen/logrus
|
||||||
version: ^1.0.6
|
version: ^1.1.1
|
||||||
- package: github.com/spf13/cobra
|
- package: github.com/spf13/cobra
|
||||||
version: ^0.0.3
|
version: ^0.0.3
|
||||||
- package: github.com/ugorji/go
|
- package: github.com/ugorji/go
|
||||||
|
|
15
sql/funcs.go
15
sql/funcs.go
|
@ -84,13 +84,11 @@ var funcs = map[string]map[int]interface{}{
|
||||||
"union": {-1: nil},
|
"union": {-1: nil},
|
||||||
|
|
||||||
// Count implementation
|
// Count implementation
|
||||||
|
|
||||||
"count": {1: nil},
|
"count": {1: nil},
|
||||||
"count.if": {2: nil},
|
"count.if": {2: nil},
|
||||||
"count.not": {2: nil},
|
"count.not": {2: nil},
|
||||||
|
|
||||||
// Purge implementation
|
// Purge implementation
|
||||||
|
|
||||||
"purge": {1: nil},
|
"purge": {1: nil},
|
||||||
"purge.if": {2: nil},
|
"purge.if": {2: nil},
|
||||||
"purge.not": {2: nil},
|
"purge.not": {2: nil},
|
||||||
|
@ -217,6 +215,19 @@ var funcs = map[string]map[int]interface{}{
|
||||||
"scrypt.compare": {2: nil},
|
"scrypt.compare": {2: nil},
|
||||||
"scrypt.generate": {1: nil},
|
"scrypt.generate": {1: nil},
|
||||||
|
|
||||||
|
// Check implementation
|
||||||
|
"is.alpha": {1: nil},
|
||||||
|
"is.alphanum": {1: nil},
|
||||||
|
"is.ascii": {1: nil},
|
||||||
|
"is.domain": {1: nil},
|
||||||
|
"is.email": {1: nil},
|
||||||
|
"is.hexadecimal": {1: nil},
|
||||||
|
"is.latitude": {1: nil},
|
||||||
|
"is.longitude": {1: nil},
|
||||||
|
"is.numeric": {1: nil},
|
||||||
|
"is.semver": {1: nil},
|
||||||
|
"is.uuid": {1: nil},
|
||||||
|
|
||||||
// Random implementation
|
// Random implementation
|
||||||
"rand": {0: nil},
|
"rand": {0: nil},
|
||||||
"guid": {0: nil},
|
"guid": {0: nil},
|
||||||
|
|
|
@ -34,11 +34,9 @@ const (
|
||||||
var (
|
var (
|
||||||
allowedTypes = []string{
|
allowedTypes = []string{
|
||||||
"array", "boolean", "circle",
|
"array", "boolean", "circle",
|
||||||
"datetime", "domain", "double",
|
"datetime", "number", "object",
|
||||||
"email", "latitude", "longitude",
|
"point", "polygon", "record",
|
||||||
"number", "object", "password",
|
"string", "uuid",
|
||||||
"phone", "point", "polygon",
|
|
||||||
"record", "string", "uuid",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
allowedAlgorithms = []string{
|
allowedAlgorithms = []string{
|
||||||
|
|
|
@ -2709,29 +2709,11 @@ func Test_Parse_Queries_Define(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
sql: `DEFINE FIELD temp ON person TYPE`,
|
sql: `DEFINE FIELD temp ON person TYPE`,
|
||||||
err: "Found `` but expected `array, boolean, circle, datetime, domain, double, email, latitude, longitude, number, object, password, phone, point, polygon, record, string, uuid`",
|
err: "Found `` but expected `array, boolean, circle, datetime, number, object, point, polygon, record, string, uuid`",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
sql: `DEFINE FIELD temp ON person TYPE something`,
|
sql: `DEFINE FIELD temp ON person TYPE something`,
|
||||||
err: "Found `something` but expected `array, boolean, circle, datetime, domain, double, email, latitude, longitude, number, object, password, phone, point, polygon, record, string, uuid`",
|
err: "Found `something` but expected `array, boolean, circle, datetime, number, object, point, polygon, record, string, uuid`",
|
||||||
},
|
|
||||||
{
|
|
||||||
sql: `DEFINE FIELD temp ON person TYPE email`,
|
|
||||||
res: &Query{Statements: []Statement{&DefineFieldStatement{
|
|
||||||
KV: "*", NS: "*", DB: "*",
|
|
||||||
Name: &Ident{"temp"},
|
|
||||||
What: Tables{&Table{"person"}},
|
|
||||||
Type: "email",
|
|
||||||
}}},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
sql: `DEFINE FIELD temp ON person TYPE phone`,
|
|
||||||
res: &Query{Statements: []Statement{&DefineFieldStatement{
|
|
||||||
KV: "*", NS: "*", DB: "*",
|
|
||||||
Name: &Ident{"temp"},
|
|
||||||
What: Tables{&Table{"person"}},
|
|
||||||
Type: "phone",
|
|
||||||
}}},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
sql: `DEFINE FIELD temp ON person TYPE array`,
|
sql: `DEFINE FIELD temp ON person TYPE array`,
|
||||||
|
@ -2769,15 +2751,6 @@ func Test_Parse_Queries_Define(t *testing.T) {
|
||||||
Type: "number",
|
Type: "number",
|
||||||
}}},
|
}}},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
sql: `DEFINE FIELD temp ON person TYPE double`,
|
|
||||||
res: &Query{Statements: []Statement{&DefineFieldStatement{
|
|
||||||
KV: "*", NS: "*", DB: "*",
|
|
||||||
Name: &Ident{"temp"},
|
|
||||||
What: Tables{&Table{"person"}},
|
|
||||||
Type: "double",
|
|
||||||
}}},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
sql: `DEFINE FIELD temp ON person TYPE record`,
|
sql: `DEFINE FIELD temp ON person TYPE record`,
|
||||||
res: &Query{Statements: []Statement{&DefineFieldStatement{
|
res: &Query{Statements: []Statement{&DefineFieldStatement{
|
||||||
|
|
|
@ -127,6 +127,8 @@ func toQuote(s string) bool {
|
||||||
continue
|
continue
|
||||||
case c == '.', c == '*':
|
case c == '.', c == '*':
|
||||||
continue
|
continue
|
||||||
|
case c == '_':
|
||||||
|
continue
|
||||||
default:
|
default:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
// Copyright © 2016 Abcum Ltd
|
|
||||||
//
|
|
||||||
// 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 chck
|
|
||||||
|
|
||||||
func IsBase64(s string) bool {
|
|
||||||
return rBase64.MatchString(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsDomain(s string) bool {
|
|
||||||
return rDomain.MatchString(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsEmail(s string) bool {
|
|
||||||
return rEmail.MatchString(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsLatitude(s string) bool {
|
|
||||||
return rLatitude.MatchString(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsLongitude(s string) bool {
|
|
||||||
return rLongitude.MatchString(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsPhone(s string) bool {
|
|
||||||
return rPhone.MatchString(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsUUID(s string) bool {
|
|
||||||
return rUUID.MatchString(s)
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
// Copyright © 2016 Abcum Ltd
|
|
||||||
//
|
|
||||||
// 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 chck
|
|
||||||
|
|
||||||
import "regexp"
|
|
||||||
|
|
||||||
const (
|
|
||||||
sBase64 string = "^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$"
|
|
||||||
sDomain string = `^([a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62}){1}(\.[a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62})*[\._]?$`
|
|
||||||
sEmail string = "^(((([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$"
|
|
||||||
sLatitude string = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$"
|
|
||||||
sLongitude string = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$"
|
|
||||||
sPhone string = `^[\s\d\+\-\(\)]+$`
|
|
||||||
sUUID string = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
rBase64 = regexp.MustCompile(sBase64)
|
|
||||||
rDomain = regexp.MustCompile(sDomain)
|
|
||||||
rEmail = regexp.MustCompile(sEmail)
|
|
||||||
rLatitude = regexp.MustCompile(sLatitude)
|
|
||||||
rLongitude = regexp.MustCompile(sLongitude)
|
|
||||||
rPhone = regexp.MustCompile(sPhone)
|
|
||||||
rUUID = regexp.MustCompile(sUUID)
|
|
||||||
)
|
|
|
@ -20,7 +20,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/abcum/surreal/sql"
|
"github.com/abcum/surreal/sql"
|
||||||
"github.com/abcum/surreal/util/chck"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func toNumber(str string) (float64, error) {
|
func toNumber(str string) (float64, error) {
|
||||||
|
@ -30,15 +29,6 @@ func toNumber(str string) (float64, error) {
|
||||||
err = fmt.Errorf("Expected a number, but found '%v'", str)
|
err = fmt.Errorf("Expected a number, but found '%v'", str)
|
||||||
|
|
||||||
}
|
}
|
||||||
return float64(int64(val)), err
|
|
||||||
}
|
|
||||||
|
|
||||||
func toDouble(str string) (float64, error) {
|
|
||||||
val, err := strconv.ParseFloat(str, 64)
|
|
||||||
if err != nil {
|
|
||||||
val = 0.0
|
|
||||||
err = fmt.Errorf("Expected a number, but found '%v'", str)
|
|
||||||
}
|
|
||||||
return float64(val), err
|
return float64(val), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,63 +107,23 @@ func ConvertTo(t, k string, obj interface{}) (val interface{}, err error) {
|
||||||
switch t {
|
switch t {
|
||||||
default:
|
default:
|
||||||
return obj, nil
|
return obj, nil
|
||||||
case "uuid":
|
|
||||||
return ConvertToUuid(obj)
|
|
||||||
case "email":
|
|
||||||
return ConvertToEmail(obj)
|
|
||||||
case "phone":
|
|
||||||
return ConvertToPhone(obj)
|
|
||||||
case "array":
|
case "array":
|
||||||
return ConvertToArray(obj)
|
return ConvertToArray(obj)
|
||||||
case "object":
|
case "object":
|
||||||
return ConvertToObject(obj)
|
return ConvertToObject(obj)
|
||||||
case "domain":
|
|
||||||
return ConvertToDomain(obj)
|
|
||||||
case "base64":
|
|
||||||
return ConvertToBase64(obj)
|
|
||||||
case "string":
|
case "string":
|
||||||
return ConvertToString(obj)
|
return ConvertToString(obj)
|
||||||
case "number":
|
case "number":
|
||||||
return ConvertToNumber(obj)
|
return ConvertToNumber(obj)
|
||||||
case "double":
|
|
||||||
return ConvertToDouble(obj)
|
|
||||||
case "boolean":
|
case "boolean":
|
||||||
return ConvertToBoolean(obj)
|
return ConvertToBoolean(obj)
|
||||||
case "datetime":
|
case "datetime":
|
||||||
return ConvertToDatetime(obj)
|
return ConvertToDatetime(obj)
|
||||||
case "latitude":
|
|
||||||
return ConvertToLatitude(obj)
|
|
||||||
case "longitude":
|
|
||||||
return ConvertToLongitude(obj)
|
|
||||||
case "record":
|
case "record":
|
||||||
return ConvertToRecord(obj, k)
|
return ConvertToRecord(obj, k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConvertToUuid(obj interface{}) (val string, err error) {
|
|
||||||
val = fmt.Sprintf("%v", obj)
|
|
||||||
if !chck.IsUUID(val) {
|
|
||||||
err = fmt.Errorf("Expected a UUID, but found '%v'", obj)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func ConvertToEmail(obj interface{}) (val string, err error) {
|
|
||||||
val = fmt.Sprintf("%v", obj)
|
|
||||||
if !chck.IsEmail(val) {
|
|
||||||
err = fmt.Errorf("Expected an email address, but found '%v'", obj)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func ConvertToPhone(obj interface{}) (val string, err error) {
|
|
||||||
val = fmt.Sprintf("%v", obj)
|
|
||||||
if !chck.IsPhone(val) {
|
|
||||||
err = fmt.Errorf("Expected a phone number, but found '%v'", obj)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func ConvertToArray(obj interface{}) (val []interface{}, err error) {
|
func ConvertToArray(obj interface{}) (val []interface{}, err error) {
|
||||||
if now, ok := obj.([]interface{}); ok {
|
if now, ok := obj.([]interface{}); ok {
|
||||||
val = now
|
val = now
|
||||||
|
@ -192,22 +142,6 @@ func ConvertToObject(obj interface{}) (val map[string]interface{}, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConvertToDomain(obj interface{}) (val string, err error) {
|
|
||||||
val = fmt.Sprintf("%v", obj)
|
|
||||||
if !chck.IsDomain(val) {
|
|
||||||
err = fmt.Errorf("Expected a domain name, but found '%v'", obj)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func ConvertToBase64(obj interface{}) (val string, err error) {
|
|
||||||
val = fmt.Sprintf("%v", obj)
|
|
||||||
if !chck.IsBase64(val) {
|
|
||||||
err = fmt.Errorf("Expected base64 data, but found '%v'", obj)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func ConvertToString(obj interface{}) (val string, err error) {
|
func ConvertToString(obj interface{}) (val string, err error) {
|
||||||
switch now := obj.(type) {
|
switch now := obj.(type) {
|
||||||
case string:
|
case string:
|
||||||
|
@ -232,19 +166,6 @@ func ConvertToNumber(obj interface{}) (val float64, err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ConvertToBoolean(obj interface{}) (val bool, err error) {
|
func ConvertToBoolean(obj interface{}) (val bool, err error) {
|
||||||
switch now := obj.(type) {
|
switch now := obj.(type) {
|
||||||
case int64:
|
case int64:
|
||||||
|
@ -270,22 +191,6 @@ func ConvertToDatetime(obj interface{}) (val time.Time, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConvertToLatitude(obj interface{}) (val float64, err error) {
|
|
||||||
str := fmt.Sprintf("%v", obj)
|
|
||||||
if !chck.IsLatitude(str) {
|
|
||||||
err = fmt.Errorf("Expected a latitude value, but found '%v'", obj)
|
|
||||||
}
|
|
||||||
return toNumber(str)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ConvertToLongitude(obj interface{}) (val float64, err error) {
|
|
||||||
str := fmt.Sprintf("%v", obj)
|
|
||||||
if !chck.IsLongitude(str) {
|
|
||||||
err = fmt.Errorf("Expected a longitude value, but found '%v'", obj)
|
|
||||||
}
|
|
||||||
return toNumber(str)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ConvertToRecord(obj interface{}, tb string) (val *sql.Thing, err error) {
|
func ConvertToRecord(obj interface{}, tb string) (val *sql.Thing, err error) {
|
||||||
switch now := obj.(type) {
|
switch now := obj.(type) {
|
||||||
case *sql.Thing:
|
case *sql.Thing:
|
||||||
|
|
|
@ -17,8 +17,6 @@ package fncs
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/abcum/surreal/util/chck"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func emailUser(ctx context.Context, args ...interface{}) (interface{}, error) {
|
func emailUser(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||||
|
@ -36,8 +34,3 @@ func emailDomain(ctx context.Context, args ...interface{}) (interface{}, error)
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func emailValid(ctx context.Context, args ...interface{}) (interface{}, error) {
|
|
||||||
v, _ := ensureString(args[0])
|
|
||||||
return chck.IsEmail(v), nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -47,14 +47,4 @@ func TestEmail(t *testing.T) {
|
||||||
So(res, ShouldEqual, nil)
|
So(res, ShouldEqual, nil)
|
||||||
})
|
})
|
||||||
|
|
||||||
Convey("email.valid(a) works properly", t, func() {
|
|
||||||
res, _ := Run(context.Background(), "email.valid", "tobie@abcum.com")
|
|
||||||
So(res, ShouldEqual, true)
|
|
||||||
})
|
|
||||||
|
|
||||||
Convey("email.valid(a) errors properly", t, func() {
|
|
||||||
res, _ := Run(context.Background(), "email.valid", "test")
|
|
||||||
So(res, ShouldEqual, false)
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -272,8 +272,6 @@ func Run(ctx context.Context, name string, args ...interface{}) (interface{}, er
|
||||||
return emailUser(ctx, args...)
|
return emailUser(ctx, args...)
|
||||||
case "email.domain":
|
case "email.domain":
|
||||||
return emailDomain(ctx, args...)
|
return emailDomain(ctx, args...)
|
||||||
case "email.valid":
|
|
||||||
return emailValid(ctx, args...)
|
|
||||||
|
|
||||||
// Bcrypt implementation
|
// Bcrypt implementation
|
||||||
case "bcrypt.compare":
|
case "bcrypt.compare":
|
||||||
|
@ -287,6 +285,30 @@ func Run(ctx context.Context, name string, args ...interface{}) (interface{}, er
|
||||||
case "scrypt.generate":
|
case "scrypt.generate":
|
||||||
return scryptGenerate(ctx, args...)
|
return scryptGenerate(ctx, args...)
|
||||||
|
|
||||||
|
// Check implementation
|
||||||
|
case "is.alpha":
|
||||||
|
return isAlpha(ctx, args...)
|
||||||
|
case "is.alphanum":
|
||||||
|
return isAlphanum(ctx, args...)
|
||||||
|
case "is.ascii":
|
||||||
|
return isAscii(ctx, args...)
|
||||||
|
case "is.domain":
|
||||||
|
return isDomain(ctx, args...)
|
||||||
|
case "is.email":
|
||||||
|
return isEmail(ctx, args...)
|
||||||
|
case "is.hexadecimal":
|
||||||
|
return isHexadecimal(ctx, args...)
|
||||||
|
case "is.latitude":
|
||||||
|
return isLatitude(ctx, args...)
|
||||||
|
case "is.longitude":
|
||||||
|
return isLongitude(ctx, args...)
|
||||||
|
case "is.numeric":
|
||||||
|
return isNumeric(ctx, args...)
|
||||||
|
case "is.semver":
|
||||||
|
return isSemver(ctx, args...)
|
||||||
|
case "is.uuid":
|
||||||
|
return isUuid(ctx, args...)
|
||||||
|
|
||||||
// Rand implementation
|
// Rand implementation
|
||||||
case "rand":
|
case "rand":
|
||||||
return rand(ctx, args...)
|
return rand(ctx, args...)
|
||||||
|
|
125
util/fncs/is.go
Normal file
125
util/fncs/is.go
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
// Copyright © 2016 Abcum Ltd
|
||||||
|
//
|
||||||
|
// 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 fncs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/mail"
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
sAlpha string = "^[a-zA-Z]+$"
|
||||||
|
sAlphanum string = "^[a-zA-Z0-9]+$"
|
||||||
|
sAscii string = "^[\x00-\x7F]+$"
|
||||||
|
sDomain string = `^([a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62}){1}(\.[a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62})*[\._]?$`
|
||||||
|
sHexadecimal string = "^[0-9a-fA-F]+$"
|
||||||
|
sLatitude string = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$"
|
||||||
|
sLongitude string = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$"
|
||||||
|
sNumeric string = "^[0-9]+$"
|
||||||
|
sSemver string = "^v?(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(-(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(\\.(0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\\+[0-9a-zA-Z-]+(\\.[0-9a-zA-Z-]+)*)?$"
|
||||||
|
sUUID string = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
rAlpha = regexp.MustCompile(sAlpha)
|
||||||
|
rAlphanum = regexp.MustCompile(sAlphanum)
|
||||||
|
rAscii = regexp.MustCompile(sAscii)
|
||||||
|
rDomain = regexp.MustCompile(sDomain)
|
||||||
|
rHexadecimal = regexp.MustCompile(sHexadecimal)
|
||||||
|
rLatitude = regexp.MustCompile(sLatitude)
|
||||||
|
rLongitude = regexp.MustCompile(sLongitude)
|
||||||
|
rNumeric = regexp.MustCompile(sNumeric)
|
||||||
|
rSemver = regexp.MustCompile(sSemver)
|
||||||
|
rUUID = regexp.MustCompile(sUUID)
|
||||||
|
)
|
||||||
|
|
||||||
|
func isAlpha(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||||
|
if val, ok := ensureString(args[0]); ok {
|
||||||
|
return rAlpha.MatchString(val), nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isAlphanum(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||||
|
if val, ok := ensureString(args[0]); ok {
|
||||||
|
return rAlphanum.MatchString(val), nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isAscii(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||||
|
if val, ok := ensureString(args[0]); ok {
|
||||||
|
return rAscii.MatchString(val), nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDomain(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||||
|
if val, ok := ensureString(args[0]); ok {
|
||||||
|
return rDomain.MatchString(val), nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isEmail(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||||
|
if val, ok := ensureString(args[0]); len(val) > 0 && ok {
|
||||||
|
pse, err := mail.ParseAddress(val)
|
||||||
|
return err == nil && val == pse.Address, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isHexadecimal(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||||
|
if val, ok := ensureString(args[0]); ok {
|
||||||
|
return rHexadecimal.MatchString(val), nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isLatitude(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||||
|
if val, ok := ensureString(args[0]); ok {
|
||||||
|
return rLatitude.MatchString(val), nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isLongitude(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||||
|
if val, ok := ensureString(args[0]); ok {
|
||||||
|
return rLongitude.MatchString(val), nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isNumeric(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||||
|
if val, ok := ensureString(args[0]); ok {
|
||||||
|
return rNumeric.MatchString(val), nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isSemver(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||||
|
if val, ok := ensureString(args[0]); ok {
|
||||||
|
return rSemver.MatchString(val), nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isUuid(ctx context.Context, args ...interface{}) (interface{}, error) {
|
||||||
|
if val, ok := ensureString(args[0]); ok {
|
||||||
|
return rUUID.MatchString(val), nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
151
util/fncs/is_test.go
Normal file
151
util/fncs/is_test.go
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
// Copyright © 2016 Abcum Ltd
|
||||||
|
//
|
||||||
|
// 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 fncs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/smartystreets/goconvey/convey"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestIs(t *testing.T) {
|
||||||
|
|
||||||
|
var res interface{}
|
||||||
|
|
||||||
|
Convey("is.alpha(a) works properly", t, func() {
|
||||||
|
res, _ = Run(context.Background(), "is.alpha", nil)
|
||||||
|
So(res, ShouldEqual, false)
|
||||||
|
res, _ = Run(context.Background(), "is.alpha", "test-©")
|
||||||
|
So(res, ShouldEqual, false)
|
||||||
|
res, _ = Run(context.Background(), "is.alpha", "aBcDe")
|
||||||
|
So(res, ShouldEqual, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("is.alphanum(a) works properly", t, func() {
|
||||||
|
res, _ = Run(context.Background(), "is.alphanum", nil)
|
||||||
|
So(res, ShouldEqual, false)
|
||||||
|
res, _ = Run(context.Background(), "is.alphanum", "test-©")
|
||||||
|
So(res, ShouldEqual, false)
|
||||||
|
res, _ = Run(context.Background(), "is.alphanum", "aB3De")
|
||||||
|
So(res, ShouldEqual, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("is.ascii(a) works properly", t, func() {
|
||||||
|
res, _ = Run(context.Background(), "is.ascii", nil)
|
||||||
|
So(res, ShouldEqual, false)
|
||||||
|
res, _ = Run(context.Background(), "is.ascii", "testing®")
|
||||||
|
So(res, ShouldEqual, false)
|
||||||
|
res, _ = Run(context.Background(), "is.ascii", "aB3De")
|
||||||
|
So(res, ShouldEqual, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("is.domain(a) works properly", t, func() {
|
||||||
|
res, _ = Run(context.Background(), "is.domain", nil)
|
||||||
|
So(res, ShouldEqual, false)
|
||||||
|
res, _ = Run(context.Background(), "is.domain", "test-©")
|
||||||
|
So(res, ShouldEqual, false)
|
||||||
|
res, _ = Run(context.Background(), "is.domain", "abcum.com")
|
||||||
|
So(res, ShouldEqual, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("is.email(a) works properly", t, func() {
|
||||||
|
res, _ = Run(context.Background(), "is.email", nil)
|
||||||
|
So(res, ShouldEqual, false)
|
||||||
|
res, _ = Run(context.Background(), "is.email", "test-©")
|
||||||
|
So(res, ShouldEqual, false)
|
||||||
|
res, _ = Run(context.Background(), "is.email", "info@abcum.com")
|
||||||
|
So(res, ShouldEqual, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("is.hexadecimal(a) works properly", t, func() {
|
||||||
|
res, _ = Run(context.Background(), "is.hexadecimal", nil)
|
||||||
|
So(res, ShouldEqual, false)
|
||||||
|
res, _ = Run(context.Background(), "is.hexadecimal", "test-©")
|
||||||
|
So(res, ShouldEqual, false)
|
||||||
|
res, _ = Run(context.Background(), "is.hexadecimal", "00bfff")
|
||||||
|
So(res, ShouldEqual, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("is.latitude(a) works properly", t, func() {
|
||||||
|
res, _ = Run(context.Background(), "is.latitude", nil)
|
||||||
|
So(res, ShouldEqual, false)
|
||||||
|
res, _ = Run(context.Background(), "is.latitude", "test-©")
|
||||||
|
So(res, ShouldEqual, false)
|
||||||
|
res, _ = Run(context.Background(), "is.latitude", 0)
|
||||||
|
So(res, ShouldEqual, true)
|
||||||
|
res, _ = Run(context.Background(), "is.latitude", -90)
|
||||||
|
So(res, ShouldEqual, true)
|
||||||
|
res, _ = Run(context.Background(), "is.latitude", +90)
|
||||||
|
So(res, ShouldEqual, true)
|
||||||
|
res, _ = Run(context.Background(), "is.latitude", "-90")
|
||||||
|
So(res, ShouldEqual, true)
|
||||||
|
res, _ = Run(context.Background(), "is.latitude", "+90")
|
||||||
|
So(res, ShouldEqual, true)
|
||||||
|
res, _ = Run(context.Background(), "is.latitude", -95)
|
||||||
|
So(res, ShouldEqual, false)
|
||||||
|
res, _ = Run(context.Background(), "is.latitude", +95)
|
||||||
|
So(res, ShouldEqual, false)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("is.longitude(a) works properly", t, func() {
|
||||||
|
res, _ = Run(context.Background(), "is.longitude", nil)
|
||||||
|
So(res, ShouldEqual, false)
|
||||||
|
res, _ = Run(context.Background(), "is.longitude", "test-©")
|
||||||
|
So(res, ShouldEqual, false)
|
||||||
|
res, _ = Run(context.Background(), "is.longitude", 0)
|
||||||
|
So(res, ShouldEqual, true)
|
||||||
|
res, _ = Run(context.Background(), "is.longitude", -180)
|
||||||
|
So(res, ShouldEqual, true)
|
||||||
|
res, _ = Run(context.Background(), "is.longitude", +180)
|
||||||
|
So(res, ShouldEqual, true)
|
||||||
|
res, _ = Run(context.Background(), "is.longitude", "-180")
|
||||||
|
So(res, ShouldEqual, true)
|
||||||
|
res, _ = Run(context.Background(), "is.longitude", "+180")
|
||||||
|
So(res, ShouldEqual, true)
|
||||||
|
res, _ = Run(context.Background(), "is.longitude", -185)
|
||||||
|
So(res, ShouldEqual, false)
|
||||||
|
res, _ = Run(context.Background(), "is.longitude", +185)
|
||||||
|
So(res, ShouldEqual, false)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("is.numeric(a) works properly", t, func() {
|
||||||
|
res, _ = Run(context.Background(), "is.numeric", nil)
|
||||||
|
So(res, ShouldEqual, false)
|
||||||
|
res, _ = Run(context.Background(), "is.numeric", "test-©")
|
||||||
|
So(res, ShouldEqual, false)
|
||||||
|
res, _ = Run(context.Background(), "is.numeric", "123456")
|
||||||
|
So(res, ShouldEqual, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("is.semver(a) works properly", t, func() {
|
||||||
|
res, _ = Run(context.Background(), "is.semver", nil)
|
||||||
|
So(res, ShouldEqual, false)
|
||||||
|
res, _ = Run(context.Background(), "is.semver", "test-©")
|
||||||
|
So(res, ShouldEqual, false)
|
||||||
|
res, _ = Run(context.Background(), "is.semver", "1.0.32")
|
||||||
|
So(res, ShouldEqual, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
Convey("is.uuid(a) works properly", t, func() {
|
||||||
|
res, _ = Run(context.Background(), "is.uuid", nil)
|
||||||
|
So(res, ShouldEqual, false)
|
||||||
|
res, _ = Run(context.Background(), "is.uuid", "test-©")
|
||||||
|
So(res, ShouldEqual, false)
|
||||||
|
res, _ = Run(context.Background(), "is.uuid", "8ddb11e8-755f-47cf-a84f-8033d1cfa1b9")
|
||||||
|
So(res, ShouldEqual, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue