Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions pkg/expression/builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -868,7 +868,11 @@ var funcs = map[string]functionClass{
ast.NameConst: &nameConstFunctionClass{baseFunctionClass{ast.NameConst, 2, 2}},
ast.ReleaseAllLocks: &releaseAllLocksFunctionClass{baseFunctionClass{ast.ReleaseAllLocks, 0, 0}},
ast.UUID: &uuidFunctionClass{baseFunctionClass{ast.UUID, 0, 0}},
ast.UUIDv4: &uuidv4FunctionClass{baseFunctionClass{ast.UUIDv4, 0, 0}},
ast.UUIDv7: &uuidv7FunctionClass{baseFunctionClass{ast.UUIDv7, 0, 0}},
ast.UUIDShort: &uuidShortFunctionClass{baseFunctionClass{ast.UUIDShort, 0, 0}},
ast.UUIDVersion: &uuidVersionFunctionClass{baseFunctionClass{ast.UUIDVersion, 1, 1}},
ast.UUIDTimestamp: &uuidTimestampFunctionClass{baseFunctionClass{ast.UUIDTimestamp, 1, 1}},
ast.VitessHash: &vitessHashFunctionClass{baseFunctionClass{ast.VitessHash, 1, 1}},
ast.UUIDToBin: &uuidToBinFunctionClass{baseFunctionClass{ast.UUIDToBin, 1, 2}},
ast.BinToUUID: &binToUUIDFunctionClass{baseFunctionClass{ast.BinToUUID, 1, 2}},
Expand Down
292 changes: 260 additions & 32 deletions pkg/expression/builtin_miscellaneous.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,66 +39,78 @@ import (
)

var (
_ functionClass = &sleepFunctionClass{}
_ functionClass = &lockFunctionClass{}
_ functionClass = &releaseLockFunctionClass{}
_ functionClass = &anyValueFunctionClass{}
_ functionClass = &binToUUIDFunctionClass{}
_ functionClass = &defaultFunctionClass{}
_ functionClass = &inetAtonFunctionClass{}
_ functionClass = &inetNtoaFunctionClass{}
_ functionClass = &inet6AtonFunctionClass{}
_ functionClass = &inet6NtoaFunctionClass{}
_ functionClass = &inetAtonFunctionClass{}
_ functionClass = &inetNtoaFunctionClass{}
_ functionClass = &isFreeLockFunctionClass{}
_ functionClass = &isIPv4FunctionClass{}
_ functionClass = &isIPv4CompatFunctionClass{}
_ functionClass = &isIPv4FunctionClass{}
_ functionClass = &isIPv4MappedFunctionClass{}
_ functionClass = &isIPv6FunctionClass{}
_ functionClass = &isUsedLockFunctionClass{}
_ functionClass = &isUUIDFunctionClass{}
_ functionClass = &lockFunctionClass{}
_ functionClass = &nameConstFunctionClass{}
_ functionClass = &releaseAllLocksFunctionClass{}
_ functionClass = &releaseLockFunctionClass{}
_ functionClass = &sleepFunctionClass{}
_ functionClass = &tidbRowChecksumFunctionClass{}
_ functionClass = &tidbShardFunctionClass{}
_ functionClass = &uuidFunctionClass{}
_ functionClass = &uuidShortFunctionClass{}
_ functionClass = &vitessHashFunctionClass{}
_ functionClass = &uuidTimestampFunctionClass{}
_ functionClass = &uuidToBinFunctionClass{}
_ functionClass = &binToUUIDFunctionClass{}
_ functionClass = &isUUIDFunctionClass{}
_ functionClass = &tidbShardFunctionClass{}
_ functionClass = &uuidv4FunctionClass{}
_ functionClass = &uuidv7FunctionClass{}
_ functionClass = &uuidVersionFunctionClass{}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why isn't there a line for uuid_timestamp?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should have been. I've added one and checked for more missing lines and I found a few.

diff <(grep -E '^type.*FunctionClass' pkg/expression/builtin_miscellaneous.go  | sort | cut -d\  -f2) <(grep -E '_ functionClass = .*FunctionClass' pkg/expression/builtin_miscellaneous.go | sort | cut -d\& -f2 | cut -d{ -f1)
diff <(grep -E '^type.*builtin' pkg/expression/builtin_miscellaneous.go  | sort | cut -d\  -f2) <(grep -E '_ builtinFunc = ' pkg/expression/builtin_miscellaneous.go | sort | cut -d\& -f2 | cut -d{ -f1)

The ones that were missing:

  • tidbRowChecksumFunctionClass
  • builtinFreeLockSig
  • builtinNameConstVectorFloat32Sig
  • builtinUsedLockSig
  • builtinUUIDTimestampSig
  • builtinUUIDv4Sig
  • builtinUUIDv7Sig
  • builtinUUIDVersionSig
  • builtinVectorFloat32AnyValueSig

I also sorted them.

The result: 35202db

Are these lines (still) needed? What happens if they are missing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like these lines might be there to ensure these types implement functionClass etc.

However this seems to already be enforced by the reference in pkg/expression/builtin.go.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could:

  • Remove these 919 lines: dveeden@af0efdb
  • Add GitHub action that runs checks

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should probably keep them and add extra github action in followup PRs. Thanks for the update!

_ functionClass = &vitessHashFunctionClass{}
)

var (
_ builtinFunc = &builtinSleepSig{}
_ builtinFunc = &builtinLockSig{}
_ builtinFunc = &builtinReleaseLockSig{}
_ builtinFunc = &builtinReleaseAllLocksSig{}
_ builtinFunc = &builtinBinToUUIDSig{}
_ builtinFunc = &builtinDecimalAnyValueSig{}
_ builtinFunc = &builtinDurationAnyValueSig{}
_ builtinFunc = &builtinIntAnyValueSig{}
_ builtinFunc = &builtinJSONAnyValueSig{}
_ builtinFunc = &builtinRealAnyValueSig{}
_ builtinFunc = &builtinStringAnyValueSig{}
_ builtinFunc = &builtinTimeAnyValueSig{}
_ builtinFunc = &builtinInetAtonSig{}
_ builtinFunc = &builtinInetNtoaSig{}
_ builtinFunc = &builtinFreeLockSig{}
_ builtinFunc = &builtinInet6AtonSig{}
_ builtinFunc = &builtinInet6NtoaSig{}
_ builtinFunc = &builtinIsIPv4Sig{}
_ builtinFunc = &builtinInetAtonSig{}
_ builtinFunc = &builtinInetNtoaSig{}
_ builtinFunc = &builtinIntAnyValueSig{}
_ builtinFunc = &builtinIsIPv4CompatSig{}
_ builtinFunc = &builtinIsIPv4MappedSig{}
_ builtinFunc = &builtinIsIPv4Sig{}
_ builtinFunc = &builtinIsIPv6Sig{}
_ builtinFunc = &builtinIsUUIDSig{}
_ builtinFunc = &builtinUUIDSig{}
_ builtinFunc = &builtinVitessHashSig{}
_ builtinFunc = &builtinUUIDToBinSig{}
_ builtinFunc = &builtinBinToUUIDSig{}

_ builtinFunc = &builtinNameConstIntSig{}
_ builtinFunc = &builtinNameConstRealSig{}
_ builtinFunc = &builtinJSONAnyValueSig{}
_ builtinFunc = &builtinLockSig{}
_ builtinFunc = &builtinNameConstDecimalSig{}
_ builtinFunc = &builtinNameConstTimeSig{}
_ builtinFunc = &builtinNameConstDurationSig{}
_ builtinFunc = &builtinNameConstStringSig{}
_ builtinFunc = &builtinNameConstIntSig{}
_ builtinFunc = &builtinNameConstJSONSig{}
_ builtinFunc = &builtinNameConstRealSig{}
_ builtinFunc = &builtinNameConstStringSig{}
_ builtinFunc = &builtinNameConstTimeSig{}
_ builtinFunc = &builtinNameConstVectorFloat32Sig{}
_ builtinFunc = &builtinRealAnyValueSig{}
_ builtinFunc = &builtinReleaseAllLocksSig{}
_ builtinFunc = &builtinReleaseLockSig{}
_ builtinFunc = &builtinSleepSig{}
_ builtinFunc = &builtinStringAnyValueSig{}
_ builtinFunc = &builtinTidbShardSig{}
_ builtinFunc = &builtinTimeAnyValueSig{}
_ builtinFunc = &builtinUsedLockSig{}
_ builtinFunc = &builtinUUIDSig{}
_ builtinFunc = &builtinUUIDTimestampSig{}
_ builtinFunc = &builtinUUIDToBinSig{}
_ builtinFunc = &builtinUUIDv4Sig{}
_ builtinFunc = &builtinUUIDv7Sig{}
_ builtinFunc = &builtinUUIDVersionSig{}
_ builtinFunc = &builtinVectorFloat32AnyValueSig{}
_ builtinFunc = &builtinVitessHashSig{}
)

const (
Expand Down Expand Up @@ -1497,7 +1509,9 @@ func (b *builtinUUIDSig) Clone() builtinFunc {
}

// evalString evals a builtinUUIDSig.
// See https://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_uuid
// See:
// - https://dev.mysql.com/doc/refman/8.4/en/miscellaneous-functions.html#function_uuid
// - https://datatracker.ietf.org/doc/html/rfc9562
func (b *builtinUUIDSig) evalString(ctx EvalContext, row chunk.Row) (d string, isNull bool, err error) {
var id uuid.UUID
id, err = uuid.NewUUID()
Expand All @@ -1508,11 +1522,225 @@ func (b *builtinUUIDSig) evalString(ctx EvalContext, row chunk.Row) (d string, i
return
}

// Function: UUID_V4()
type uuidv4FunctionClass struct {
baseFunctionClass
}

func (c *uuidv4FunctionClass) getFunction(ctx BuildContext, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, err
}
bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString)
if err != nil {
return nil, err
}
charset, collate := ctx.GetCharsetInfo()
bf.tp.SetCharset(charset)
bf.tp.SetCollate(collate)
bf.tp.SetFlen(36)
sig := &builtinUUIDv4Sig{bf}
sig.setPbCode(tipb.ScalarFuncSig_UUID)
return sig, nil
}

type builtinUUIDv4Sig struct {
baseBuiltinFunc

// NOTE: Any new fields added here must be thread-safe or immutable during execution,
// as this expression may be shared across sessions.
// If a field does not meet these requirements, set SafeToShareAcrossSession to false.
}

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

// evalString evals a builtinUUIDv4Sig.
func (b *builtinUUIDv4Sig) evalString(ctx EvalContext, row chunk.Row) (d string, isNull bool, err error) {
var id uuid.UUID
id, err = uuid.NewRandom()
if err != nil {
return
}
d = id.String()
return
}

// Function: UUID_V7()
type uuidv7FunctionClass struct {
baseFunctionClass
}

func (c *uuidv7FunctionClass) getFunction(ctx BuildContext, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, err
}
bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETString)
if err != nil {
return nil, err
}
charset, collate := ctx.GetCharsetInfo()
bf.tp.SetCharset(charset)
bf.tp.SetCollate(collate)
bf.tp.SetFlen(36)
sig := &builtinUUIDv7Sig{bf}
sig.setPbCode(tipb.ScalarFuncSig_UUID)
return sig, nil
}

type builtinUUIDv7Sig struct {
baseBuiltinFunc

// NOTE: Any new fields added here must be thread-safe or immutable during execution,
// as this expression may be shared across sessions.
// If a field does not meet these requirements, set SafeToShareAcrossSession to false.
}

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

// evalString evals a builtinUUIDv7Sig.
func (b *builtinUUIDv7Sig) evalString(ctx EvalContext, row chunk.Row) (d string, isNull bool, err error) {
var id uuid.UUID
id, err = uuid.NewV7()
if err != nil {
return
}
d = id.String()
return
}

// Function: UUID_VERSION()
type uuidVersionFunctionClass struct {
baseFunctionClass
}

func (c *uuidVersionFunctionClass) getFunction(ctx BuildContext, 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.SetFlen(10)
sig := &builtinUUIDVersionSig{bf}
return sig, nil
}

type builtinUUIDVersionSig struct {
baseBuiltinFunc

// NOTE: Any new fields added here must be thread-safe or immutable during execution,
// as this expression may be shared across sessions.
// If a field does not meet these requirements, set SafeToShareAcrossSession to false.
}

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

// evalInt evaluates a builtinUUIDVersionSig.
func (b *builtinUUIDVersionSig) evalInt(ctx EvalContext, row chunk.Row) (int64, bool, error) {
val, isNull, err := b.args[0].EvalString(ctx, row)
if isNull || err != nil {
return 0, isNull, err
}
u, err := uuid.Parse(val)
if err != nil {
return 0, isNull, err
}
return int64(u.Version()), false, nil
}

// Function: UUID_TIMESTAMP()
type uuidTimestampFunctionClass struct {
baseFunctionClass
}

func (c *uuidTimestampFunctionClass) getFunction(ctx BuildContext, args []Expression) (builtinFunc, error) {
if err := c.verifyArgs(args); err != nil {
return nil, err
}
bf, err := newBaseBuiltinFuncWithTp(ctx, c.funcName, args, types.ETDecimal, types.ETString)
if err != nil {
return nil, err
}
bf.tp.SetFlen(18)
bf.tp.SetDecimalUnderLimit(6)
sig := &builtinUUIDTimestampSig{bf}
return sig, nil
}

type builtinUUIDTimestampSig struct {
baseBuiltinFunc

// NOTE: Any new fields added here must be thread-safe or immutable during execution,
// as this expression may be shared across sessions.
// If a field does not meet these requirements, set SafeToShareAcrossSession to false.
}

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

// evalInt evaluates a builtinUUIDTimestampSig.
func (b *builtinUUIDTimestampSig) evalDecimal(ctx EvalContext, row chunk.Row) (*types.MyDecimal, bool, error) {
val, isNull, err := b.args[0].EvalString(ctx, row)
if isNull || err != nil {
return new(types.MyDecimal), isNull, err
}
u, err := uuid.Parse(val)
if err != nil {
return new(types.MyDecimal), isNull, err
}

switch u.Version() {
case 1:
case 6:
case 7:
default:
// No timestamp, return NULL
return new(types.MyDecimal), true, nil
}

s, ns := u.Time().UnixTime()
r := new(types.MyDecimal)
r.FromInt((s * 1000000) + (ns / 1000))
err = r.Shift(-6)
if err != nil {
return new(types.MyDecimal), isNull, err
}
err = r.Round(r, 6, types.ModeHalfUp)
if err != nil {
return new(types.MyDecimal), isNull, err
}

return r, false, nil
}

type uuidShortFunctionClass struct {
baseFunctionClass
}

func (c *uuidShortFunctionClass) getFunction(ctx BuildContext, args []Expression) (builtinFunc, error) {
// This should be:
//
// (server_id & 255) << 56
// + (server_startup_time_in_seconds << 24)
// + incremented_variable++;
//
// But we have a noop server_id
return nil, ErrFunctionNotExists.GenWithStackByArgs("FUNCTION", "UUID_SHORT")
}

Expand Down
20 changes: 20 additions & 0 deletions pkg/expression/builtin_threadsafe_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading