expression, parser: add built-in func is_uuid (#30318)
This commit is contained in:
@ -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))
|
||||
|
||||
@ -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}},
|
||||
|
||||
@ -57,6 +57,7 @@ var (
|
||||
_ functionClass = &vitessHashFunctionClass{}
|
||||
_ functionClass = &uuidToBinFunctionClass{}
|
||||
_ functionClass = &binToUUIDFunctionClass{}
|
||||
_ functionClass = &isUUIDFunctionClass{}
|
||||
)
|
||||
|
||||
var (
|
||||
@ -78,6 +79,7 @@ var (
|
||||
_ builtinFunc = &builtinIsIPv4CompatSig{}
|
||||
_ builtinFunc = &builtinIsIPv4MappedSig{}
|
||||
_ builtinFunc = &builtinIsIPv6Sig{}
|
||||
_ builtinFunc = &builtinIsUUIDSig{}
|
||||
_ builtinFunc = &builtinUUIDSig{}
|
||||
_ builtinFunc = &builtinVitessHashSig{}
|
||||
_ builtinFunc = &builtinUUIDToBinSig{}
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
2
go.mod
2
go.mod
@ -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
|
||||
|
||||
4
go.sum
4
go.sum
@ -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=
|
||||
|
||||
@ -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"
|
||||
|
||||
Reference in New Issue
Block a user