diff --git a/go/vt/vtgate/evalengine/compiler_test.go b/go/vt/vtgate/evalengine/compiler_test.go index e1e905a6efa..efcf0036acb 100644 --- a/go/vt/vtgate/evalengine/compiler_test.go +++ b/go/vt/vtgate/evalengine/compiler_test.go @@ -587,3 +587,65 @@ func TestBindVarLiteral(t *testing.T) { }) } } + +func TestCompilerNonConstant(t *testing.T) { + var testCases = []struct { + expression string + }{ + { + expression: "RANDOM_BYTES(4)", + }, + { + expression: "UUID()", + }, + } + + for _, tc := range testCases { + t.Run(tc.expression, func(t *testing.T) { + expr, err := sqlparser.ParseExpr(tc.expression) + if err != nil { + t.Fatal(err) + } + + cfg := &evalengine.Config{ + Collation: collations.CollationUtf8mb4ID, + Optimization: evalengine.OptimizationLevelCompile, + } + + converted, err := evalengine.Translate(expr, cfg) + if err != nil { + t.Fatal(err) + } + + env := evalengine.EmptyExpressionEnv() + var prev string + for i := 0; i < 1000; i++ { + expected, err := env.Evaluate(evalengine.Deoptimize(converted)) + if err != nil { + t.Fatal(err) + } + if expected.String() == prev { + t.Fatalf("constant evaluation from eval engine: got %s multiple times", expected.String()) + } + prev = expected.String() + } + + if cfg.CompilerErr != nil { + t.Fatalf("bad compilation: %v", cfg.CompilerErr) + } + + // re-run the same evaluation multiple times to ensure results are always consistent + for i := 0; i < 1000; i++ { + res, err := env.EvaluateVM(converted.(*evalengine.CompiledExpr)) + if err != nil { + t.Fatal(err) + } + + if res.String() == prev { + t.Fatalf("constant evaluation from eval engine: got %s multiple times", res.String()) + } + prev = res.String() + } + }) + } +} diff --git a/go/vt/vtgate/evalengine/fn_misc.go b/go/vt/vtgate/evalengine/fn_misc.go index 96522a2314f..04770c387af 100644 --- a/go/vt/vtgate/evalengine/fn_misc.go +++ b/go/vt/vtgate/evalengine/fn_misc.go @@ -586,6 +586,10 @@ func (call *builtinUUID) compile(c *compiler) (ctype, error) { return ctype{Type: sqltypes.VarChar, Flag: 0, Col: collationUtf8mb3}, nil } +func (call *builtinUUID) constant() bool { + return false +} + func (call *builtinUUIDToBin) eval(env *ExpressionEnv) (eval, error) { arg, err := call.arg1(env) if arg == nil || err != nil {