From 0249912a499f3bb0eda2411ab444e227b2cf3976 Mon Sep 17 00:00:00 2001 From: leo <1518440211@qq.com> Date: Mon, 2 Sep 2024 19:08:24 +0800 Subject: [PATCH 1/2] [Feature Request]: strcmp function #15359 --- pkg/sql/plan/function/func_binary.go | 8 ++++++++ pkg/sql/plan/function/function_id.go | 2 ++ pkg/sql/plan/function/list_builtIn.go | 21 +++++++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/pkg/sql/plan/function/func_binary.go b/pkg/sql/plan/function/func_binary.go index 8ce5661238b91..0fd32a5832024 100644 --- a/pkg/sql/plan/function/func_binary.go +++ b/pkg/sql/plan/function/func_binary.go @@ -2198,6 +2198,14 @@ func EndsWith(ivecs []*vector.Vector, result vector.FunctionResultWrapper, proc return opBinaryBytesBytesToFixed[bool](ivecs, result, proc, length, bytes.HasSuffix, selectList) } +func Strcmp(ivecs []*vector.Vector, result vector.FunctionResultWrapper, proc *process.Process, length int) (err error) { + return opBinaryStrStrToFixed[int8](ivecs, result, proc, length, strcmp, nil) +} + +func strcmp(s1, s2 string) int8 { + return (int8)(strings.Compare(s1, s2)) +} + // https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html#function_sha2 func SHA2Func(args []*vector.Vector, result vector.FunctionResultWrapper, _ *process.Process, length int, selectList *FunctionSelectList) (err error) { res := vector.MustFunctionResult[types.Varlena](result) diff --git a/pkg/sql/plan/function/function_id.go b/pkg/sql/plan/function/function_id.go index 2752b794f04e8..8df12ba580606 100644 --- a/pkg/sql/plan/function/function_id.go +++ b/pkg/sql/plan/function/function_id.go @@ -200,6 +200,7 @@ const ( STARTSWITH STDDEV_POP STDDEV_SAMPLE + STRCMP SUBSTR SUM SYSDATE @@ -539,6 +540,7 @@ var functionIdRegister = map[string]int32{ "sin": SIN, "sinh": SINH, "space": SPACE, + "strcmp": STRCMP, "tan": TAN, "week": WEEK, "weekday": WEEKDAY, diff --git a/pkg/sql/plan/function/list_builtIn.go b/pkg/sql/plan/function/list_builtIn.go index 258ce105b43ae..07dfc46486cd8 100644 --- a/pkg/sql/plan/function/list_builtIn.go +++ b/pkg/sql/plan/function/list_builtIn.go @@ -1517,6 +1517,27 @@ var supportedStringBuiltIns = []FuncNew{ }, }, + // function `strcmp` + { + functionId: STRCMP, + class: plan.Function_STRICT, + layout: STANDARD_FUNCTION, + checkFn: fixedTypeMatch, + + Overloads: []overload{ + { + overloadId: 0, + args: []types.T{types.T_varchar, types.T_varchar}, + retType: func(parameters []types.Type) types.Type { + return types.T_int8.ToType() + }, + newOp: func() executeLogicOfOverload { + return Strcmp + }, + }, + }, + }, + // function `prefix_eq` { functionId: PREFIX_EQ, From fd484bc6b1001f713a346904e6b5cd454c999b28 Mon Sep 17 00:00:00 2001 From: leo <1518440211@qq.com> Date: Tue, 3 Sep 2024 14:10:35 +0800 Subject: [PATCH 2/2] [Feature Request]: strcmp function #15359 --- pkg/sql/plan/function/func_binary.go | 10 ++++- pkg/sql/plan/function/func_binary_test.go | 55 +++++++++++++++++++++++ pkg/sql/plan/function/list_builtIn.go | 2 +- 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/pkg/sql/plan/function/func_binary.go b/pkg/sql/plan/function/func_binary.go index 0fd32a5832024..b537a0d402847 100644 --- a/pkg/sql/plan/function/func_binary.go +++ b/pkg/sql/plan/function/func_binary.go @@ -2198,12 +2198,18 @@ func EndsWith(ivecs []*vector.Vector, result vector.FunctionResultWrapper, proc return opBinaryBytesBytesToFixed[bool](ivecs, result, proc, length, bytes.HasSuffix, selectList) } -func Strcmp(ivecs []*vector.Vector, result vector.FunctionResultWrapper, proc *process.Process, length int) (err error) { +func Strcmp(ivecs []*vector.Vector, result vector.FunctionResultWrapper, proc *process.Process, length int, _ *FunctionSelectList) (err error) { return opBinaryStrStrToFixed[int8](ivecs, result, proc, length, strcmp, nil) } func strcmp(s1, s2 string) int8 { - return (int8)(strings.Compare(s1, s2)) + if s1 == s2 { + return 0 + } + if s1 < s2 { + return -1 + } + return 1 } // https://dev.mysql.com/doc/refman/8.0/en/encryption-functions.html#function_sha2 diff --git a/pkg/sql/plan/function/func_binary_test.go b/pkg/sql/plan/function/func_binary_test.go index 5353407297e10..abf6ea991a01b 100644 --- a/pkg/sql/plan/function/func_binary_test.go +++ b/pkg/sql/plan/function/func_binary_test.go @@ -2166,6 +2166,61 @@ func TestInstr(t *testing.T) { } } +// STRCMP +func initStrcmpTestCase() []tcTemp { + cases := []struct { + s1 string + s2 string + wants int8 + }{ + {"", "", 0}, + {"", "a", -1}, + {"a", "", 1}, + {"0", "0", 0}, + {"0", "1", -1}, + {"0", "-1", 1}, + {"ab", "abc", -1}, + {"abcd", "abc", 1}, + {"abce", "abcd", 1}, + {"abce", "abcda", 1}, + {"我们", "我", 1}, + {"我们", "wo", 1}, + {"我们", "woo", 1}, + {"我们", "我们", 0}, + {"我 们", "我们", -1}, + {"-ae", "我", -1}, + {":=符号只允许在函数中使用,即只能在声明局部变量的时候使用,而var没有这个限制", "a b cd ", -1}, + {"符号只允许在函数中使用,即只能在声明局部变量的时候使用,而var没有这个限制", "a b cd ", 1}, + {"符号只允许在函数中使用,即只能在声明局部变量的时候使用,而var没有这个限制", "符号只允许在函数中使用,即只能在声明局部变量的时候使用,而var没有这个限制", 0}, + } + + var testInputs = make([]tcTemp, 0, len(cases)) + for _, c := range cases { + testInputs = append(testInputs, tcTemp{ + info: "test strcmp ", + inputs: []FunctionTestInput{ + // Create a input entry + NewFunctionTestInput(types.T_varchar.ToType(), []string{c.s1}, []bool{}), + NewFunctionTestInput(types.T_varchar.ToType(), []string{c.s2}, []bool{}), + }, + expect: NewFunctionTestResult(types.T_int8.ToType(), false, []int8{c.wants}, []bool{}), + }) + } + + return testInputs +} + +func TestStrcmp(t *testing.T) { + testCases := initStrcmpTestCase() + + proc := testutil.NewProcess() + for _, tc := range testCases { + fcTC := NewFunctionTestCase(proc, tc.inputs, tc.expect, Strcmp) + s, info := fcTC.Run() + require.True(t, s, fmt.Sprintf("case is '%s', err info is '%s'", tc.info, info)) + } +} + // Left func initLeftTestCase() []tcTemp { cases := []struct { diff --git a/pkg/sql/plan/function/list_builtIn.go b/pkg/sql/plan/function/list_builtIn.go index 07dfc46486cd8..1b92d6d67dfa3 100644 --- a/pkg/sql/plan/function/list_builtIn.go +++ b/pkg/sql/plan/function/list_builtIn.go @@ -1529,7 +1529,7 @@ var supportedStringBuiltIns = []FuncNew{ overloadId: 0, args: []types.T{types.T_varchar, types.T_varchar}, retType: func(parameters []types.Type) types.Type { - return types.T_int8.ToType() + return types.T_int32.ToType() }, newOp: func() executeLogicOfOverload { return Strcmp