Skip to content

Commit

Permalink
expression, parser: add built-in func is_uuid (#30318)
Browse files Browse the repository at this point in the history
  • Loading branch information
unconsolable authored Dec 6, 2021
1 parent bc08b50 commit 3337405
Show file tree
Hide file tree
Showing 9 changed files with 118 additions and 4 deletions.
2 changes: 1 addition & 1 deletion executor/show_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1394,7 +1394,7 @@ func (s *testSuite5) TestShowBuiltin(c *C) {
res := tk.MustQuery("show builtins;")
c.Assert(res, NotNil)
rows := res.Rows()
const builtinFuncNum = 273
const builtinFuncNum = 274
c.Assert(builtinFuncNum, Equals, len(rows))
c.Assert("abs", Equals, rows[0][0].(string))
c.Assert("yearweek", Equals, rows[builtinFuncNum-1][0].(string))
Expand Down
1 change: 1 addition & 0 deletions expression/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,7 @@ var funcs = map[string]functionClass{
ast.IsIPv4Mapped: &isIPv4MappedFunctionClass{baseFunctionClass{ast.IsIPv4Mapped, 1, 1}},
ast.IsIPv6: &isIPv6FunctionClass{baseFunctionClass{ast.IsIPv6, 1, 1}},
ast.IsUsedLock: &isUsedLockFunctionClass{baseFunctionClass{ast.IsUsedLock, 1, 1}},
ast.IsUUID: &isUUIDFunctionClass{baseFunctionClass{ast.IsUUID, 1, 1}},
ast.MasterPosWait: &masterPosWaitFunctionClass{baseFunctionClass{ast.MasterPosWait, 2, 4}},
ast.NameConst: &nameConstFunctionClass{baseFunctionClass{ast.NameConst, 2, 2}},
ast.ReleaseAllLocks: &releaseAllLocksFunctionClass{baseFunctionClass{ast.ReleaseAllLocks, 0, 0}},
Expand Down
43 changes: 43 additions & 0 deletions expression/builtin_miscellaneous.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ var (
_ functionClass = &vitessHashFunctionClass{}
_ functionClass = &uuidToBinFunctionClass{}
_ functionClass = &binToUUIDFunctionClass{}
_ functionClass = &isUUIDFunctionClass{}
)

var (
Expand All @@ -78,6 +79,7 @@ var (
_ builtinFunc = &builtinIsIPv4CompatSig{}
_ builtinFunc = &builtinIsIPv4MappedSig{}
_ builtinFunc = &builtinIsIPv6Sig{}
_ builtinFunc = &builtinIsUUIDSig{}
_ builtinFunc = &builtinUUIDSig{}
_ builtinFunc = &builtinVitessHashSig{}
_ builtinFunc = &builtinUUIDToBinSig{}
Expand Down Expand Up @@ -862,6 +864,47 @@ func (c *isUsedLockFunctionClass) getFunction(ctx sessionctx.Context, args []Exp
return nil, errFunctionNotExists.GenWithStackByArgs("FUNCTION", "IS_USED_LOCK")
}

type isUUIDFunctionClass struct {
baseFunctionClass
}

func (c *isUUIDFunctionClass) getFunction(ctx sessionctx.Context, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, err
}
bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETInt, types.ETString)
if err != nil {
return nil, err
}
bf.tp.Flen = 1
sig := &builtinIsUUIDSig{bf}
sig.setPbCode(tipb.ScalarFuncSig_IsUUID)
return sig, nil
}

type builtinIsUUIDSig struct {
baseBuiltinFunc
}

func (b *builtinIsUUIDSig) Clone() builtinFunc {
newSig := &builtinIsUUIDSig{}
newSig.cloneFrom(&b.baseBuiltinFunc)
return newSig
}

// evalInt evals a builtinIsUUIDSig.
// See https://dev.mysql.com/doc/refman/8.0/en/miscellaneous-functions.html#function_is-uuid
func (b *builtinIsUUIDSig) evalInt(row chunk.Row) (int64, bool, error) {
val, isNull, err := b.args[0].EvalString(b.ctx, row)
if err != nil || isNull {
return 0, isNull, err
}
if _, err = uuid.Parse(val); err != nil {
return 0, false, nil
}
return 1, false, nil
}

type masterPosWaitFunctionClass struct {
baseFunctionClass
}
Expand Down
36 changes: 36 additions & 0 deletions expression/builtin_miscellaneous_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,42 @@ func TestIsIPv4(t *testing.T) {
trequire.DatumEqual(t, types.NewDatum(0), r)
}

func TestIsUUID(t *testing.T) {
t.Parallel()
ctx := createContext(t)
tests := []struct {
uuid string
expect interface{}
}{
{"6ccd780c-baba-1026-9564-5b8c656024db", 1},
{"6CCD780C-BABA-1026-9564-5B8C656024DB", 1},
{"6ccd780cbaba102695645b8c656024db", 1},
{"{6ccd780c-baba-1026-9564-5b8c656024db}", 1},
{"6ccd780c-baba-1026-9564-5b8c6560", 0},
{"6CCD780C-BABA-1026-9564-5B8C656024DQ", 0},
// This is a bug in google/uuid#60
{"{99a9ad03-5298-11ec-8f5c-00ff90147ac3*", 1},
// This is a format google/uuid support, while mysql doesn't
{"urn:uuid:99a9ad03-5298-11ec-8f5c-00ff90147ac3", 1},
}

fc := funcs[ast.IsUUID]
for _, test := range tests {
uuid := types.NewStringDatum(test.uuid)
f, err := fc.getFunction(ctx, datumsToConstants([]types.Datum{uuid}))
require.NoError(t, err)
result, err := evalBuiltinFunc(f, chunk.Row{})
require.NoError(t, err)
trequire.DatumEqual(t, types.NewDatum(test.expect), result)
}

var argNull types.Datum
f, _ := fc.getFunction(ctx, datumsToConstants([]types.Datum{argNull}))
r, err := evalBuiltinFunc(f, chunk.Row{})
require.NoError(t, err)
require.True(t, r.IsNull())
}

func TestUUID(t *testing.T) {
t.Parallel()
ctx := createContext(t)
Expand Down
30 changes: 30 additions & 0 deletions expression/builtin_miscellaneous_vec.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,36 @@ func (b *builtinIsIPv6Sig) vecEvalInt(input *chunk.Chunk, result *chunk.Column)
return nil
}

func (b *builtinIsUUIDSig) vectorized() bool {
return true
}

func (b *builtinIsUUIDSig) vecEvalInt(input *chunk.Chunk, result *chunk.Column) error {
n := input.NumRows()
buf, err := b.bufAllocator.get()
if err != nil {
return err
}
defer b.bufAllocator.put(buf)
if err := b.args[0].VecEvalString(b.ctx, input, buf); err != nil {
return err
}
result.ResizeInt64(n, false)
i64s := result.Int64s()
result.MergeNulls(buf)
for i := 0; i < n; i++ {
if result.IsNull(i) {
continue
}
if _, err = uuid.Parse(buf.GetString(i)); err != nil {
i64s[i] = 0
} else {
i64s[i] = 1
}
}
return nil
}

func (b *builtinNameConstStringSig) vectorized() bool {
return true
}
Expand Down
3 changes: 3 additions & 0 deletions expression/builtin_miscellaneous_vec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ var vecBuiltinMiscellaneousCases = map[string][]vecExprBenchCase{
{retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString}, geners: []dataGenerator{&uuidBinGener{newDefaultRandGen()}}},
{retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString, types.ETInt}, geners: []dataGenerator{&uuidBinGener{newDefaultRandGen()}}},
},
ast.IsUUID: {
{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETString}, geners: []dataGenerator{&uuidStrGener{newDefaultRandGen()}}},
},
}

func TestVectorizedBuiltinMiscellaneousEvalOneVec(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ require (
github.com/pingcap/sysutil v0.0.0-20210730114356-fcd8a63f68c5
github.com/pingcap/tidb-tools v5.2.2-0.20211019062242-37a8bef2fa17+incompatible
github.com/pingcap/tidb/parser v0.0.0-20211011031125-9b13dc409c5e
github.com/pingcap/tipb v0.0.0-20211116093845-e9b045a0bdf8
github.com/pingcap/tipb v0.0.0-20211201080053-bd104bb270ba
github.com/prometheus/client_golang v1.5.1
github.com/prometheus/client_model v0.2.0
github.com/prometheus/common v0.9.1
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -597,8 +597,8 @@ github.com/pingcap/tidb-dashboard v0.0.0-20211008050453-a25c25809529/go.mod h1:O
github.com/pingcap/tidb-dashboard v0.0.0-20211107164327-80363dfbe884/go.mod h1:OCXbZTBTIMRcIt0jFsuCakZP+goYRv6IjawKbwLS2TQ=
github.com/pingcap/tidb-tools v5.2.2-0.20211019062242-37a8bef2fa17+incompatible h1:c7+izmker91NkjkZ6FgTlmD4k1A5FLOAq+li6Ki2/GY=
github.com/pingcap/tidb-tools v5.2.2-0.20211019062242-37a8bef2fa17+incompatible/go.mod h1:XGdcy9+yqlDSEMTpOXnwf3hiTeqrV6MN/u1se9N8yIM=
github.com/pingcap/tipb v0.0.0-20211116093845-e9b045a0bdf8 h1:Vu/6oq8EFNWgyXRHiclNzTKIu+YKHPCSI/Ba5oVrLtM=
github.com/pingcap/tipb v0.0.0-20211116093845-e9b045a0bdf8/go.mod h1:A7mrd7WHBl1o63LE2bIBGEJMTNWXqhgmYiOvMLxozfs=
github.com/pingcap/tipb v0.0.0-20211201080053-bd104bb270ba h1:Tt5W/maVBUbG+wxg2nfc88Cqj/HiWYb0TJQ2Rfi0UOQ=
github.com/pingcap/tipb v0.0.0-20211201080053-bd104bb270ba/go.mod h1:A7mrd7WHBl1o63LE2bIBGEJMTNWXqhgmYiOvMLxozfs=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
Expand Down
1 change: 1 addition & 0 deletions parser/ast/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ const (
IsIPv4Mapped = "is_ipv4_mapped"
IsIPv6 = "is_ipv6"
IsUsedLock = "is_used_lock"
IsUUID = "is_uuid"
MasterPosWait = "master_pos_wait"
NameConst = "name_const"
ReleaseAllLocks = "release_all_locks"
Expand Down

0 comments on commit 3337405

Please sign in to comment.