diff --git a/pkg/expression/builtin_other.go b/pkg/expression/builtin_other.go index aa6fd599f7e5b..e0375bda60a1e 100644 --- a/pkg/expression/builtin_other.go +++ b/pkg/expression/builtin_other.go @@ -1304,6 +1304,8 @@ func (c *valuesFunctionClass) getFunction(ctx BuildContext, args []Expression) ( sig = &builtinValuesDurationSig{baseBuiltinFunc: bf, offset: c.offset} case types.ETJson: sig = &builtinValuesJSONSig{baseBuiltinFunc: bf, offset: c.offset} + case types.ETVectorFloat32: + sig = &builtinValuesVectorFloat32Sig{baseBuiltinFunc: bf, offset: c.offset} default: return nil, errors.Errorf("%s is not supported for VALUES()", c.tp.EvalType()) } @@ -1595,6 +1597,43 @@ func (b *builtinValuesJSONSig) evalJSON(ctx EvalContext, _ chunk.Row) (types.Bin return types.BinaryJSON{}, true, errors.Errorf("Session current insert values len %d and column's offset %v don't match", row.Len(), b.offset) } +type builtinValuesVectorFloat32Sig struct { + baseBuiltinFunc + contextopt.SessionVarsPropReader + + offset int +} + +func (b *builtinValuesVectorFloat32Sig) Clone() builtinFunc { + newSig := &builtinValuesVectorFloat32Sig{offset: b.offset} + newSig.cloneFrom(&b.baseBuiltinFunc) + return newSig +} + +func (b *builtinValuesVectorFloat32Sig) RequiredOptionalEvalProps() OptionalEvalPropKeySet { + return b.SessionVarsPropReader.RequiredOptionalEvalProps() +} + +// evalVectorFloat32 evals a builtinValuesVectorFloat32Sig. +// See https://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_values +func (b *builtinValuesVectorFloat32Sig) evalVectorFloat32(ctx EvalContext, _ chunk.Row) (types.VectorFloat32, bool, error) { + sessionvar, err := b.GetSessionVars(ctx) + if err != nil { + return types.ZeroVectorFloat32, true, err + } + row := sessionvar.CurrInsertValues + if row.IsEmpty() { + return types.ZeroVectorFloat32, true, nil + } + if b.offset < row.Len() { + if row.IsNull(b.offset) { + return types.ZeroVectorFloat32, true, nil + } + return row.GetVectorFloat32(b.offset), false, nil + } + return types.ZeroVectorFloat32, true, errors.Errorf("Session current insert values len %d and column's offset %v don't match", row.Len(), b.offset) +} + type bitCountFunctionClass struct { baseFunctionClass } diff --git a/pkg/expression/integration_test/BUILD.bazel b/pkg/expression/integration_test/BUILD.bazel index 22eddae5b4cc2..433770906f4ab 100644 --- a/pkg/expression/integration_test/BUILD.bazel +++ b/pkg/expression/integration_test/BUILD.bazel @@ -8,7 +8,7 @@ go_test( "main_test.go", ], flaky = True, - shard_count = 40, + shard_count = 41, deps = [ "//pkg/config", "//pkg/domain", diff --git a/pkg/expression/integration_test/integration_test.go b/pkg/expression/integration_test/integration_test.go index 2cbfdf85d2496..0c7b14e9143a9 100644 --- a/pkg/expression/integration_test/integration_test.go +++ b/pkg/expression/integration_test/integration_test.go @@ -563,6 +563,21 @@ func TestVectorFunctions(t *testing.T) { tk.MustQuery(`SELECT VEC_L2_NORM('[0,1]');`).Check(testkit.Rows("1")) } +func TestVectorMiscFunctions(t *testing.T) { + store := testkit.CreateMockStore(t) + + tk := testkit.NewTestKit(t, store) + tk.MustExec("USE test;") + + tk.MustExec("CREATE TABLE a(pk INT PRIMARY KEY, c VECTOR(3), time INT);") + tk.MustExec("INSERT INTO a VALUES (1, '[1,2,3]', 5);") + tk.MustQuery(`SELECT * FROM a;`).Check(testkit.Rows("1 [1,2,3] 5")) + tk.MustExec("INSERT INTO a VALUES (1, '[1,1,1]', 10) ON DUPLICATE KEY UPDATE time=VALUES(time), c=VALUES(c);") + tk.MustQuery(`SELECT * FROM a;`).Check(testkit.Rows("1 [1,1,1] 10")) + tk.MustExec("INSERT INTO a VALUES (1, '[1,5,7]', 15) ON DUPLICATE KEY UPDATE time=VEC_DIMS(c), c=VALUES(c)+VALUES(c);") + tk.MustQuery(`SELECT * FROM a;`).Check(testkit.Rows("1 [2,10,14] 3")) +} + func TestGetLock(t *testing.T) { ctx := context.Background() store := testkit.CreateMockStore(t, mockstore.WithStoreType(mockstore.EmbedUnistore))