2184 lines
103 KiB
Go
2184 lines
103 KiB
Go
// Copyright 2017 PingCAP, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package expression
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/gogo/protobuf/proto"
|
|
"github.com/pingcap/failpoint"
|
|
"github.com/pingcap/tidb/pkg/kv"
|
|
"github.com/pingcap/tidb/pkg/parser/ast"
|
|
"github.com/pingcap/tidb/pkg/parser/charset"
|
|
"github.com/pingcap/tidb/pkg/parser/mysql"
|
|
"github.com/pingcap/tidb/pkg/types"
|
|
"github.com/pingcap/tidb/pkg/util/mock"
|
|
"github.com/pingcap/tipb/go-tipb"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func genColumn(tp byte, id int64) *Column {
|
|
return &Column{
|
|
RetType: types.NewFieldType(tp),
|
|
ID: id,
|
|
Index: int(id),
|
|
}
|
|
}
|
|
|
|
func TestConstant2Pb(t *testing.T) {
|
|
t.Skip("constant pb has changed")
|
|
var constExprs []Expression
|
|
ctx := mock.NewContext()
|
|
client := new(mock.Client)
|
|
pushDownCtx := NewPushDownContextFromSessionVars(ctx, ctx.GetSessionVars(), client)
|
|
|
|
// can be transformed
|
|
constValue := new(Constant)
|
|
constValue.Value = types.NewDatum(nil)
|
|
require.Equal(t, types.KindNull, constValue.Value.Kind())
|
|
constExprs = append(constExprs, constValue)
|
|
|
|
constValue = new(Constant)
|
|
constValue.Value = types.NewDatum(int64(100))
|
|
require.Equal(t, types.KindInt64, constValue.Value.Kind())
|
|
constExprs = append(constExprs, constValue)
|
|
|
|
constValue = new(Constant)
|
|
constValue.Value = types.NewDatum(uint64(100))
|
|
require.Equal(t, types.KindUint64, constValue.Value.Kind())
|
|
constExprs = append(constExprs, constValue)
|
|
|
|
constValue = new(Constant)
|
|
constValue.Value = types.NewDatum("100")
|
|
require.Equal(t, types.KindString, constValue.Value.Kind())
|
|
constExprs = append(constExprs, constValue)
|
|
|
|
constValue = new(Constant)
|
|
constValue.Value = types.NewDatum([]byte{'1', '2', '4', 'c'})
|
|
require.Equal(t, types.KindBytes, constValue.Value.Kind())
|
|
constExprs = append(constExprs, constValue)
|
|
|
|
constValue = new(Constant)
|
|
constValue.Value = types.NewDatum(types.NewDecFromInt(110))
|
|
require.Equal(t, types.KindMysqlDecimal, constValue.Value.Kind())
|
|
constExprs = append(constExprs, constValue)
|
|
|
|
constValue = new(Constant)
|
|
constValue.Value = types.NewDatum(types.Duration{})
|
|
require.Equal(t, types.KindMysqlDuration, constValue.Value.Kind())
|
|
constExprs = append(constExprs, constValue)
|
|
|
|
// can not be transformed
|
|
constValue = new(Constant)
|
|
constValue.Value = types.NewDatum(float32(100))
|
|
require.Equal(t, types.KindFloat32, constValue.Value.Kind())
|
|
constExprs = append(constExprs, constValue)
|
|
|
|
constValue = new(Constant)
|
|
constValue.Value = types.NewDatum(float64(100))
|
|
require.Equal(t, types.KindFloat64, constValue.Value.Kind())
|
|
constExprs = append(constExprs, constValue)
|
|
|
|
constValue = new(Constant)
|
|
constValue.Value = types.NewDatum(types.Enum{Name: "A", Value: 19})
|
|
require.Equal(t, types.KindMysqlEnum, constValue.Value.Kind())
|
|
constExprs = append(constExprs, constValue)
|
|
|
|
pushed, remained := PushDownExprs(pushDownCtx, constExprs, kv.UnSpecified)
|
|
require.Len(t, pushed, len(constExprs)-3)
|
|
require.Len(t, remained, 3)
|
|
|
|
pbExprs, err := ExpressionsToPBList(ctx, constExprs, client)
|
|
require.NoError(t, err)
|
|
jsons := []string{
|
|
"{\"tp\":0,\"sig\":0}",
|
|
"{\"tp\":1,\"val\":\"gAAAAAAAAGQ=\",\"sig\":0}",
|
|
"{\"tp\":2,\"val\":\"AAAAAAAAAGQ=\",\"sig\":0}",
|
|
"{\"tp\":5,\"val\":\"MTAw\",\"sig\":0}",
|
|
"{\"tp\":6,\"val\":\"MTI0Yw==\",\"sig\":0}",
|
|
"{\"tp\":102,\"val\":\"AwCAbg==\",\"sig\":0}",
|
|
"{\"tp\":103,\"val\":\"gAAAAAAAAAA=\",\"sig\":0}",
|
|
}
|
|
for i, pbExpr := range pbExprs {
|
|
if i+3 < len(pbExprs) {
|
|
js, err := json.Marshal(pbExpr)
|
|
require.NoError(t, err)
|
|
require.Equal(t, jsons[i], string(js))
|
|
} else {
|
|
require.Nil(t, pbExpr)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestColumn2Pb(t *testing.T) {
|
|
var colExprs []Expression
|
|
ctx := mock.NewContext()
|
|
client := new(mock.Client)
|
|
pushDownCtx := NewPushDownContextFromSessionVars(ctx, ctx.GetSessionVars(), client)
|
|
|
|
colExprs = append(colExprs, genColumn(mysql.TypeSet, 1))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeGeometry, 2))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeUnspecified, 3))
|
|
|
|
pushed, remained := PushDownExprs(pushDownCtx, colExprs, kv.UnSpecified)
|
|
require.Len(t, pushed, 0)
|
|
require.Len(t, remained, len(colExprs))
|
|
|
|
for _, col := range colExprs { // cannot be pushed down
|
|
_, err := ExpressionsToPBList(ctx, []Expression{col}, client)
|
|
require.Error(t, err)
|
|
}
|
|
|
|
colExprs = colExprs[:0]
|
|
colExprs = append(colExprs, genColumn(mysql.TypeTiny, 1))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeShort, 2))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeLong, 3))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeFloat, 4))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeDouble, 5))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeNull, 6))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeTimestamp, 7))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeLonglong, 8))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeInt24, 9))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeDate, 10))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeDuration, 11))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeDatetime, 12))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeYear, 13))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeVarchar, 15))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeJSON, 16))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeNewDecimal, 17))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeTinyBlob, 18))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeMediumBlob, 19))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeLongBlob, 20))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeBlob, 21))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeVarString, 22))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeString, 23))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeEnum, 24))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeBit, 25))
|
|
pushed, remained = PushDownExprs(pushDownCtx, colExprs, kv.UnSpecified)
|
|
require.Len(t, pushed, len(colExprs))
|
|
require.Len(t, remained, 0)
|
|
|
|
pbExprs, err := ExpressionsToPBList(ctx, colExprs, client)
|
|
require.NoError(t, err)
|
|
jsons := []string{
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":1,\"flag\":0,\"flen\":4,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":2,\"flag\":0,\"flen\":6,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAAAM=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":11,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAAAQ=\",\"sig\":0,\"field_type\":{\"tp\":4,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAAAU=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAAAY=\",\"sig\":0,\"field_type\":{\"tp\":6,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAAAc=\",\"sig\":0,\"field_type\":{\"tp\":7,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAAAg=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAAAk=\",\"sig\":0,\"field_type\":{\"tp\":9,\"flag\":0,\"flen\":9,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAAAo=\",\"sig\":0,\"field_type\":{\"tp\":10,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAAAs=\",\"sig\":0,\"field_type\":{\"tp\":11,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAAAw=\",\"sig\":0,\"field_type\":{\"tp\":12,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAAA0=\",\"sig\":0,\"field_type\":{\"tp\":13,\"flag\":0,\"flen\":4,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAAA8=\",\"sig\":0,\"field_type\":{\"tp\":15,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-46,\"charset\":\"utf8mb4\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAABA=\",\"sig\":0,\"field_type\":{\"tp\":245,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAABE=\",\"sig\":0,\"field_type\":{\"tp\":246,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAABI=\",\"sig\":0,\"field_type\":{\"tp\":249,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAABM=\",\"sig\":0,\"field_type\":{\"tp\":250,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAABQ=\",\"sig\":0,\"field_type\":{\"tp\":251,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAABU=\",\"sig\":0,\"field_type\":{\"tp\":252,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAABY=\",\"sig\":0,\"field_type\":{\"tp\":253,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-46,\"charset\":\"utf8mb4\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAABc=\",\"sig\":0,\"field_type\":{\"tp\":254,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-46,\"charset\":\"utf8mb4\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAABg=\",\"sig\":0,\"field_type\":{\"tp\":247,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAABk=\",\"sig\":0,\"field_type\":{\"tp\":16,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
}
|
|
for i, pbExpr := range pbExprs {
|
|
require.NotNil(t, pbExprs)
|
|
js, err := json.Marshal(pbExpr)
|
|
require.NoError(t, err)
|
|
require.Equalf(t, jsons[i], string(js), "%v\n", i)
|
|
}
|
|
|
|
for _, expr := range colExprs {
|
|
expr.(*Column).ID = 0
|
|
expr.(*Column).Index = 0
|
|
}
|
|
|
|
pushed, remained = PushDownExprs(pushDownCtx, colExprs, kv.UnSpecified)
|
|
require.Len(t, pushed, len(colExprs))
|
|
require.Len(t, remained, 0)
|
|
}
|
|
|
|
func TestCompareFunc2Pb(t *testing.T) {
|
|
var compareExprs = make([]Expression, 0)
|
|
ctx := mock.NewContext()
|
|
client := new(mock.Client)
|
|
pushDownCtx := NewPushDownContextFromSessionVars(ctx, ctx.GetSessionVars(), client)
|
|
|
|
funcNames := []string{ast.LT, ast.LE, ast.GT, ast.GE, ast.EQ, ast.NE, ast.NullEQ}
|
|
for _, funcName := range funcNames {
|
|
fc, err := NewFunction(mock.NewContext(), funcName, types.NewFieldType(mysql.TypeUnspecified), genColumn(mysql.TypeLonglong, 1), genColumn(mysql.TypeLonglong, 2))
|
|
require.NoError(t, err)
|
|
compareExprs = append(compareExprs, fc)
|
|
}
|
|
|
|
pushed, remained := PushDownExprs(pushDownCtx, compareExprs, kv.UnSpecified)
|
|
require.Len(t, pushed, len(compareExprs))
|
|
require.Len(t, remained, 0)
|
|
|
|
pbExprs, err := ExpressionsToPBList(ctx, compareExprs, client)
|
|
require.NoError(t, err)
|
|
require.Len(t, pbExprs, len(compareExprs))
|
|
jsons := []string{
|
|
"{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":100,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":110,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":120,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":130,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":140,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":150,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":160,\"field_type\":{\"tp\":8,\"flag\":524417,\"flen\":1,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
}
|
|
for i, pbExpr := range pbExprs {
|
|
require.NotNil(t, pbExprs)
|
|
js, err := json.Marshal(pbExpr)
|
|
require.NoError(t, err)
|
|
require.Equal(t, jsons[i], string(js))
|
|
}
|
|
}
|
|
|
|
func TestLikeFunc2Pb(t *testing.T) {
|
|
var likeFuncs []Expression
|
|
ctx := mock.NewContext()
|
|
client := new(mock.Client)
|
|
|
|
retTp := types.NewFieldType(mysql.TypeString)
|
|
retTp.SetFlag(retTp.GetFlag() | mysql.NotNullFlag)
|
|
retTp.SetCharset(charset.CharsetUTF8)
|
|
retTp.SetCollate(charset.CollationUTF8)
|
|
args := []Expression{
|
|
&Constant{RetType: retTp, Value: types.NewDatum("string")},
|
|
&Constant{RetType: retTp, Value: types.NewDatum("pattern")},
|
|
&Constant{RetType: retTp, Value: types.NewDatum(`%abc%`)},
|
|
&Constant{RetType: retTp, Value: types.NewDatum("\\")},
|
|
}
|
|
retTp = types.NewFieldType(mysql.TypeUnspecified)
|
|
fc, err := NewFunction(ctx, ast.Like, retTp, args[0], args[1], args[3])
|
|
require.NoError(t, err)
|
|
likeFuncs = append(likeFuncs, fc)
|
|
|
|
fc, err = NewFunction(ctx, ast.Like, retTp, args[0], args[2], args[3])
|
|
require.NoError(t, err)
|
|
likeFuncs = append(likeFuncs, fc)
|
|
|
|
pbExprs, err := ExpressionsToPBList(ctx, likeFuncs, client)
|
|
require.NoError(t, err)
|
|
results := []string{
|
|
`{"tp":10000,"children":[{"tp":5,"val":"c3RyaW5n","sig":0,"field_type":{"tp":254,"flag":1,"flen":-1,"decimal":-1,"collate":-83,"charset":"utf8","array":false},"has_distinct":false},{"tp":5,"val":"cGF0dGVybg==","sig":0,"field_type":{"tp":254,"flag":1,"flen":-1,"decimal":-1,"collate":-83,"charset":"utf8","array":false},"has_distinct":false},{"tp":10000,"val":"CAA=","children":[{"tp":5,"val":"XA==","sig":0,"field_type":{"tp":254,"flag":1,"flen":-1,"decimal":-1,"collate":-83,"charset":"utf8","array":false},"has_distinct":false}],"sig":30,"field_type":{"tp":8,"flag":129,"flen":-1,"decimal":0,"collate":-83,"charset":"binary","array":false},"has_distinct":false}],"sig":4310,"field_type":{"tp":8,"flag":524416,"flen":1,"decimal":0,"collate":-83,"charset":"binary","array":false},"has_distinct":false}`,
|
|
`{"tp":10000,"children":[{"tp":5,"val":"c3RyaW5n","sig":0,"field_type":{"tp":254,"flag":1,"flen":-1,"decimal":-1,"collate":-83,"charset":"utf8","array":false},"has_distinct":false},{"tp":5,"val":"JWFiYyU=","sig":0,"field_type":{"tp":254,"flag":1,"flen":-1,"decimal":-1,"collate":-83,"charset":"utf8","array":false},"has_distinct":false},{"tp":10000,"val":"CAA=","children":[{"tp":5,"val":"XA==","sig":0,"field_type":{"tp":254,"flag":1,"flen":-1,"decimal":-1,"collate":-83,"charset":"utf8","array":false},"has_distinct":false}],"sig":30,"field_type":{"tp":8,"flag":129,"flen":-1,"decimal":0,"collate":-83,"charset":"binary","array":false},"has_distinct":false}],"sig":4310,"field_type":{"tp":8,"flag":524416,"flen":1,"decimal":0,"collate":-83,"charset":"binary","array":false},"has_distinct":false}`,
|
|
}
|
|
for i, pbExpr := range pbExprs {
|
|
js, err := json.Marshal(pbExpr)
|
|
require.NoError(t, err)
|
|
require.Equal(t, results[i], string(js))
|
|
}
|
|
}
|
|
|
|
func TestArithmeticalFunc2Pb(t *testing.T) {
|
|
var arithmeticalFuncs = make([]Expression, 0)
|
|
ctx := mock.NewContext()
|
|
client := new(mock.Client)
|
|
|
|
funcNames := []string{ast.Plus, ast.Minus, ast.Mul, ast.Div}
|
|
for _, funcName := range funcNames {
|
|
fc, err := NewFunction(
|
|
mock.NewContext(),
|
|
funcName,
|
|
types.NewFieldType(mysql.TypeUnspecified),
|
|
genColumn(mysql.TypeDouble, 1),
|
|
genColumn(mysql.TypeDouble, 2))
|
|
require.NoError(t, err)
|
|
arithmeticalFuncs = append(arithmeticalFuncs, fc)
|
|
}
|
|
|
|
jsons := make(map[string]string)
|
|
jsons[ast.Plus] = "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":200,\"field_type\":{\"tp\":5,\"flag\":128,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}"
|
|
jsons[ast.Minus] = "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":204,\"field_type\":{\"tp\":5,\"flag\":128,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}"
|
|
jsons[ast.Mul] = "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":208,\"field_type\":{\"tp\":5,\"flag\":128,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}"
|
|
jsons[ast.Div] = "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":211,\"field_type\":{\"tp\":5,\"flag\":128,\"flen\":23,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}"
|
|
jsons[ast.Mod] = "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":215,\"field_type\":{\"tp\":5,\"flag\":128,\"flen\":23,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}"
|
|
|
|
pbExprs, err := ExpressionsToPBList(ctx, arithmeticalFuncs, client)
|
|
require.NoError(t, err)
|
|
for i, pbExpr := range pbExprs {
|
|
require.NotNil(t, pbExpr)
|
|
js, err := json.Marshal(pbExpr)
|
|
require.NoError(t, err)
|
|
require.Equalf(t, jsons[funcNames[i]], string(js), "%v\n", funcNames[i])
|
|
}
|
|
|
|
// IntDiv
|
|
fc, err := NewFunction(
|
|
mock.NewContext(),
|
|
ast.IntDiv,
|
|
types.NewFieldType(mysql.TypeUnspecified),
|
|
genColumn(mysql.TypeLonglong, 1),
|
|
genColumn(mysql.TypeLonglong, 2))
|
|
require.NoError(t, err)
|
|
pbExprs, err = ExpressionsToPBList(ctx, []Expression{fc}, client)
|
|
require.NoError(t, err)
|
|
js, err := json.Marshal(pbExprs[0])
|
|
require.NoError(t, err)
|
|
expectedJs := "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":8,\"flag\":0,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":213,\"field_type\":{\"tp\":8,\"flag\":128,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}"
|
|
require.Equalf(t, expectedJs, string(js), "%v\n", ast.IntDiv)
|
|
}
|
|
|
|
func TestDateFunc2Pb(t *testing.T) {
|
|
ctx := mock.NewContext()
|
|
client := new(mock.Client)
|
|
|
|
fc, err := NewFunction(
|
|
mock.NewContext(),
|
|
ast.DateFormat,
|
|
types.NewFieldType(mysql.TypeUnspecified),
|
|
genColumn(mysql.TypeDatetime, 1),
|
|
genColumn(mysql.TypeString, 2))
|
|
require.NoError(t, err)
|
|
funcs := []Expression{fc}
|
|
pbExprs, err := ExpressionsToPBList(ctx, funcs, client)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, pbExprs[0])
|
|
js, err := json.Marshal(pbExprs[0])
|
|
require.NoError(t, err)
|
|
require.Equal(t, "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":12,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":254,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-46,\"charset\":\"utf8mb4\",\"array\":false},\"has_distinct\":false}],\"sig\":6001,\"field_type\":{\"tp\":253,\"flag\":0,\"flen\":0,\"decimal\":-1,\"collate\":-46,\"charset\":\"utf8mb4\",\"array\":false},\"has_distinct\":false}", string(js))
|
|
}
|
|
|
|
func TestLogicalFunc2Pb(t *testing.T) {
|
|
var logicalFuncs = make([]Expression, 0)
|
|
ctx := mock.NewContext()
|
|
client := new(mock.Client)
|
|
|
|
funcNames := []string{ast.LogicAnd, ast.LogicOr, ast.LogicXor, ast.UnaryNot}
|
|
for i, funcName := range funcNames {
|
|
args := []Expression{genColumn(mysql.TypeTiny, 1)}
|
|
if i+1 < len(funcNames) {
|
|
args = append(args, genColumn(mysql.TypeTiny, 2))
|
|
}
|
|
fc, err := NewFunction(
|
|
mock.NewContext(),
|
|
funcName,
|
|
types.NewFieldType(mysql.TypeUnspecified),
|
|
args...,
|
|
)
|
|
require.NoError(t, err)
|
|
logicalFuncs = append(logicalFuncs, fc)
|
|
}
|
|
|
|
pbExprs, err := ExpressionsToPBList(ctx, logicalFuncs, client)
|
|
require.NoError(t, err)
|
|
jsons := []string{
|
|
"{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":1,\"flag\":0,\"flen\":4,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":1,\"flag\":0,\"flen\":4,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":3101,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":1,\"flag\":0,\"flen\":4,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":1,\"flag\":0,\"flen\":4,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":3102,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":1,\"flag\":0,\"flen\":4,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":1,\"flag\":0,\"flen\":4,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":3103,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":1,\"flag\":0,\"flen\":4,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":3104,\"field_type\":{\"tp\":8,\"flag\":524416,\"flen\":1,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
}
|
|
for i, pbExpr := range pbExprs {
|
|
js, err := json.Marshal(pbExpr)
|
|
require.NoError(t, err)
|
|
require.Equal(t, jsons[i], string(js))
|
|
}
|
|
}
|
|
|
|
func TestBitwiseFunc2Pb(t *testing.T) {
|
|
var bitwiseFuncs = make([]Expression, 0)
|
|
ctx := mock.NewContext()
|
|
client := new(mock.Client)
|
|
|
|
funcNames := []string{ast.And, ast.Or, ast.Xor, ast.LeftShift, ast.RightShift, ast.BitNeg}
|
|
for i, funcName := range funcNames {
|
|
args := []Expression{genColumn(mysql.TypeLong, 1)}
|
|
if i+1 < len(funcNames) {
|
|
args = append(args, genColumn(mysql.TypeLong, 2))
|
|
}
|
|
fc, err := NewFunction(
|
|
mock.NewContext(),
|
|
funcName,
|
|
types.NewFieldType(mysql.TypeUnspecified),
|
|
args...,
|
|
)
|
|
require.NoError(t, err)
|
|
bitwiseFuncs = append(bitwiseFuncs, fc)
|
|
}
|
|
|
|
pbExprs, err := ExpressionsToPBList(ctx, bitwiseFuncs, client)
|
|
require.NoError(t, err)
|
|
jsons := []string{
|
|
"{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":11,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":11,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":3118,\"field_type\":{\"tp\":8,\"flag\":160,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":11,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":11,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":3119,\"field_type\":{\"tp\":8,\"flag\":160,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":11,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":11,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":3120,\"field_type\":{\"tp\":8,\"flag\":160,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":11,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":11,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":3129,\"field_type\":{\"tp\":8,\"flag\":160,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":11,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":11,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":3130,\"field_type\":{\"tp\":8,\"flag\":160,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":11,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":3121,\"field_type\":{\"tp\":8,\"flag\":160,\"flen\":20,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
}
|
|
for i, pbExpr := range pbExprs {
|
|
js, err := json.Marshal(pbExpr)
|
|
require.NoError(t, err)
|
|
require.Equal(t, jsons[i], string(js))
|
|
}
|
|
}
|
|
|
|
func TestControlFunc2Pb(t *testing.T) {
|
|
var controlFuncs = make([]Expression, 0)
|
|
ctx := mock.NewContext()
|
|
client := new(mock.Client)
|
|
|
|
funcNames := []string{
|
|
ast.Case,
|
|
ast.If,
|
|
ast.Ifnull,
|
|
}
|
|
for i, funcName := range funcNames {
|
|
args := []Expression{genColumn(mysql.TypeLong, 1)}
|
|
args = append(args, genColumn(mysql.TypeLong, 2))
|
|
if i < 2 {
|
|
args = append(args, genColumn(mysql.TypeLong, 3))
|
|
}
|
|
fc, err := NewFunction(
|
|
mock.NewContext(),
|
|
funcName,
|
|
types.NewFieldType(mysql.TypeUnspecified),
|
|
args...,
|
|
)
|
|
require.NoError(t, err)
|
|
controlFuncs = append(controlFuncs, fc)
|
|
}
|
|
|
|
pbExprs, err := ExpressionsToPBList(ctx, controlFuncs, client)
|
|
require.NoError(t, err)
|
|
jsons := []string{
|
|
"{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":11,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":11,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAM=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":11,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":4208,\"field_type\":{\"tp\":3,\"flag\":128,\"flen\":11,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":11,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":11,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAM=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":11,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":4107,\"field_type\":{\"tp\":3,\"flag\":128,\"flen\":11,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":11,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":11,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":4101,\"field_type\":{\"tp\":3,\"flag\":128,\"flen\":11,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
"null",
|
|
}
|
|
for i, pbExpr := range pbExprs {
|
|
js, err := json.Marshal(pbExpr)
|
|
require.NoError(t, err)
|
|
require.Equal(t, jsons[i], string(js))
|
|
}
|
|
}
|
|
|
|
func TestOtherFunc2Pb(t *testing.T) {
|
|
var otherFuncs = make([]Expression, 0)
|
|
client := new(mock.Client)
|
|
|
|
funcNames := []string{ast.Coalesce, ast.IsNull}
|
|
for _, funcName := range funcNames {
|
|
fc, err := NewFunction(
|
|
mock.NewContext(),
|
|
funcName,
|
|
types.NewFieldType(mysql.TypeUnspecified),
|
|
genColumn(mysql.TypeLong, 1),
|
|
)
|
|
require.NoError(t, err)
|
|
otherFuncs = append(otherFuncs, fc)
|
|
}
|
|
|
|
pbExprs, err := ExpressionsToPBList(mock.NewContext(), otherFuncs, client)
|
|
require.NoError(t, err)
|
|
jsons := map[string]string{
|
|
ast.Coalesce: "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":11,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":4201,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":11,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
ast.IsNull: "{\"tp\":10000,\"children\":[{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":3,\"flag\":0,\"flen\":11,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}],\"sig\":3116,\"field_type\":{\"tp\":8,\"flag\":524417,\"flen\":1,\"decimal\":0,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false}",
|
|
}
|
|
for i, pbExpr := range pbExprs {
|
|
js, err := json.Marshal(pbExpr)
|
|
require.NoError(t, err)
|
|
require.Equal(t, jsons[funcNames[i]], string(js))
|
|
}
|
|
}
|
|
|
|
func TestJsonPushDownToFlash(t *testing.T) {
|
|
ctx := mock.NewContext()
|
|
client := new(mock.Client)
|
|
pushDownCtx := NewPushDownContextFromSessionVars(ctx, ctx.GetSessionVars(), client)
|
|
|
|
exprs := make([]Expression, 0)
|
|
|
|
jsonColumn := genColumn(mysql.TypeJSON, 1)
|
|
intColumn := genColumn(mysql.TypeLonglong, 2)
|
|
stringColumn := genColumn(mysql.TypeString, 5)
|
|
|
|
// functions that can be pushdown to tiflash
|
|
// json_length
|
|
function, err := NewFunction(mock.NewContext(), ast.JSONLength, types.NewFieldType(mysql.TypeLonglong), jsonColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// json_extract
|
|
function, err = NewFunction(mock.NewContext(), ast.JSONExtract, types.NewFieldType(mysql.TypeJSON), jsonColumn, stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// json_unquote argument is cast(json as string)
|
|
subFunc, subErr := NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeString), jsonColumn)
|
|
require.NoError(t, subErr)
|
|
function, err = NewFunction(mock.NewContext(), ast.JSONUnquote, types.NewFieldType(mysql.TypeString), subFunc)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// json_unquote's argument is not cast(json as string)
|
|
function, err = NewFunction(mock.NewContext(), ast.JSONUnquote, types.NewFieldType(mysql.TypeString), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// json_array
|
|
function, err = NewFunction(mock.NewContext(), ast.JSONArray, types.NewFieldType(mysql.TypeJSON), jsonColumn, jsonColumn, jsonColumn, jsonColumn, jsonColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// json_depth
|
|
function, err = NewFunction(mock.NewContext(), ast.JSONDepth, types.NewFieldType(mysql.TypeLonglong), jsonColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// json_contains_path
|
|
function, err = NewFunction(mock.NewContext(), ast.JSONContainsPath, types.NewFieldType(mysql.TypeLonglong), jsonColumn, stringColumn, stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// json_valid
|
|
/// json_valid_others
|
|
function, err = NewFunction(mock.NewContext(), ast.JSONValid, types.NewFieldType(mysql.TypeLonglong), intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
/// json_valid_json
|
|
function, err = NewFunction(mock.NewContext(), ast.JSONValid, types.NewFieldType(mysql.TypeLonglong), jsonColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
/// json_valid_string
|
|
function, err = NewFunction(mock.NewContext(), ast.JSONValid, types.NewFieldType(mysql.TypeLonglong), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// json_keys
|
|
/// 1 arg
|
|
function, err = NewFunction(mock.NewContext(), ast.JSONKeys, types.NewFieldType(mysql.TypeJSON), jsonColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
/// 2 args
|
|
function, err = NewFunction(mock.NewContext(), ast.JSONKeys, types.NewFieldType(mysql.TypeJSON), jsonColumn, stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastJsonAsString
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeString), jsonColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastJsonAsJson
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeJSON), jsonColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// IfNullJson
|
|
function, err = NewFunction(mock.NewContext(), ast.Ifnull, types.NewFieldType(mysql.TypeJSON), jsonColumn, jsonColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// IfJson
|
|
function, err = NewFunction(mock.NewContext(), ast.If, types.NewFieldType(mysql.TypeJSON), intColumn, jsonColumn, jsonColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// JsonIsNull is not implement, for function json_col is null, it will be converted to cast(json as string) is null
|
|
function, err = NewFunction(mock.NewContext(), ast.IsNull, types.NewFieldType(mysql.TypeLonglong), jsonColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CaseWhenJson
|
|
function, err = NewFunction(mock.NewContext(), ast.Case, types.NewFieldType(mysql.TypeJSON), intColumn, jsonColumn, intColumn, jsonColumn, jsonColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CoalesceJson
|
|
function, err = NewFunction(mock.NewContext(), ast.Coalesce, types.NewFieldType(mysql.TypeJSON), jsonColumn, jsonColumn, jsonColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
pushed, remained := PushDownExprs(pushDownCtx, exprs, kv.TiFlash)
|
|
require.Len(t, pushed, len(exprs))
|
|
require.Len(t, remained, 0)
|
|
|
|
// functions that can not be pushed to tiflash
|
|
exprs = exprs[:0]
|
|
// LTJson
|
|
function, err = NewFunction(mock.NewContext(), ast.LT, types.NewFieldType(mysql.TypeLonglong), jsonColumn, jsonColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// LEJson
|
|
function, err = NewFunction(mock.NewContext(), ast.LE, types.NewFieldType(mysql.TypeLonglong), jsonColumn, jsonColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// GTJson
|
|
function, err = NewFunction(mock.NewContext(), ast.GT, types.NewFieldType(mysql.TypeLonglong), jsonColumn, jsonColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// GEJson
|
|
function, err = NewFunction(mock.NewContext(), ast.GE, types.NewFieldType(mysql.TypeLonglong), jsonColumn, jsonColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// EQJson
|
|
function, err = NewFunction(mock.NewContext(), ast.EQ, types.NewFieldType(mysql.TypeLonglong), jsonColumn, jsonColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// NEJson
|
|
function, err = NewFunction(mock.NewContext(), ast.NE, types.NewFieldType(mysql.TypeLonglong), jsonColumn, jsonColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// InJson
|
|
function, err = NewFunction(mock.NewContext(), ast.In, types.NewFieldType(mysql.TypeLonglong), jsonColumn, jsonColumn, jsonColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
pushed, remained = PushDownExprs(pushDownCtx, exprs, kv.TiFlash)
|
|
require.Len(t, pushed, 0)
|
|
require.Len(t, remained, len(exprs))
|
|
}
|
|
|
|
func TestExprPushDownToFlash(t *testing.T) {
|
|
ctx := mock.NewContext()
|
|
client := new(mock.Client)
|
|
pushDownCtx := NewPushDownContextFromSessionVars(ctx, ctx.GetSessionVars(), client)
|
|
|
|
exprs := make([]Expression, 0)
|
|
|
|
intColumn := genColumn(mysql.TypeLonglong, 2)
|
|
realColumn := genColumn(mysql.TypeDouble, 3)
|
|
decimalColumn := genColumn(mysql.TypeNewDecimal, 4)
|
|
decimalColumn.RetType.SetDecimal(mysql.MaxDecimalScale)
|
|
decimalColumn.RetType.SetFlen(mysql.MaxDecimalWidth)
|
|
stringColumn := genColumn(mysql.TypeString, 5)
|
|
datetimeColumn := genColumn(mysql.TypeDatetime, 6)
|
|
binaryStringColumn := genColumn(mysql.TypeString, 7)
|
|
binaryStringColumn.RetType.SetCollate(charset.CollationBin)
|
|
int32Column := genColumn(mysql.TypeLong, 8)
|
|
float32Column := genColumn(mysql.TypeFloat, 9)
|
|
enumColumn := genColumn(mysql.TypeEnum, 10)
|
|
durationColumn := genColumn(mysql.TypeDuration, 11)
|
|
// uint64 col
|
|
uintColumn := genColumn(mysql.TypeLonglong, 12)
|
|
uintColumn.RetType.AddFlag(mysql.UnsignedFlag)
|
|
|
|
function, err := NewFunction(mock.NewContext(), ast.Lpad, types.NewFieldType(mysql.TypeString), stringColumn, int32Column, stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// truncate
|
|
function, err = NewFunction(mock.NewContext(), ast.Truncate, types.NewFieldType(mysql.TypeNewDecimal), decimalColumn, intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
function, err = NewFunction(mock.NewContext(), ast.Truncate, types.NewFieldType(mysql.TypeDouble), float32Column, intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
function, err = NewFunction(mock.NewContext(), ast.Truncate, types.NewFieldType(mysql.TypeLong), intColumn, intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// rpad
|
|
function, err = NewFunction(mock.NewContext(), ast.Rpad, types.NewFieldType(mysql.TypeString), stringColumn, int32Column, stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
function, err = NewFunction(mock.NewContext(), ast.If, types.NewFieldType(mysql.TypeLonglong), intColumn, intColumn, intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
function, err = NewFunction(mock.NewContext(), ast.BitNeg, types.NewFieldType(mysql.TypeLonglong), intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
function, err = NewFunction(mock.NewContext(), ast.Xor, types.NewFieldType(mysql.TypeLonglong), intColumn, intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ExtractDatetime: can be pushed
|
|
extractDatetimeUnitCol := new(Constant)
|
|
extractDatetimeUnitCol.Value = types.NewStringDatum("day")
|
|
extractDatetimeUnitCol.RetType = types.NewFieldType(mysql.TypeString)
|
|
function, err = NewFunction(mock.NewContext(), ast.Extract, types.NewFieldType(mysql.TypeLonglong), extractDatetimeUnitCol, datetimeColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ExtractDuration
|
|
extractDurationUnitCol := new(Constant)
|
|
extractDurationUnitCol.Value = types.NewStringDatum("microsecond")
|
|
extractDurationUnitCol.RetType = types.NewFieldType(mysql.TypeString)
|
|
function, err = NewFunction(mock.NewContext(), ast.Extract, types.NewFieldType(mysql.TypeLonglong), extractDurationUnitCol, durationColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastIntAsInt
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeLonglong), intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastRealAsInt
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeLonglong), realColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastDecimalAsInt
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeLonglong), decimalColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastDecimalAsDouble
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeDouble), decimalColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastStringAsInt
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeLonglong), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastTimeAsInt
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeLonglong), datetimeColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
validDecimalType := types.NewFieldType(mysql.TypeNewDecimal)
|
|
validDecimalType.SetFlen(20)
|
|
validDecimalType.SetDecimal(2)
|
|
// CastIntAsDecimal
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, validDecimalType, intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastRealAsDecimal
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, validDecimalType, realColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastDecimalAsDecimal
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, validDecimalType, decimalColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastStringAsDecimal
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, validDecimalType, stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastTimeAsDecimal
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, validDecimalType, datetimeColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastIntAsString
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeString), intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastRealAsString
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeString), realColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastDecimalAsString
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeString), decimalColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastStringAsString
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeString), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastIntAsTime
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeDatetime), intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastRealAsTime
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeDatetime), realColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastDecimalAsTime
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeDatetime), decimalColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastTimeAsTime
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeDatetime), datetimeColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastStringAsReal
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeDouble), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// Substring2ArgsUTF8
|
|
function, err = NewFunction(mock.NewContext(), ast.Substr, types.NewFieldType(mysql.TypeString), stringColumn, intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// Substring3ArgsUTF8
|
|
function, err = NewFunction(mock.NewContext(), ast.Substr, types.NewFieldType(mysql.TypeString), stringColumn, intColumn, intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// sqrt
|
|
function, err = NewFunction(mock.NewContext(), ast.Sqrt, types.NewFieldType(mysql.TypeDouble), realColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_CeilReal
|
|
function, err = NewFunction(mock.NewContext(), ast.Ceil, types.NewFieldType(mysql.TypeDouble), realColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_CeilIntToInt
|
|
function, err = NewFunction(mock.NewContext(), ast.Ceil, types.NewFieldType(mysql.TypeLonglong), intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_CeilDecimalToInt
|
|
function, err = NewFunction(mock.NewContext(), ast.Ceil, types.NewFieldType(mysql.TypeLonglong), decimalColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_CeilDecToDec
|
|
function, err = NewFunction(mock.NewContext(), ast.Ceil, types.NewFieldType(mysql.TypeNewDecimal), decimalColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_FloorReal
|
|
function, err = NewFunction(mock.NewContext(), ast.Floor, types.NewFieldType(mysql.TypeDouble), realColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_FloorIntToInt
|
|
function, err = NewFunction(mock.NewContext(), ast.Floor, types.NewFieldType(mysql.TypeLonglong), intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_FloorDecToInt
|
|
function, err = NewFunction(mock.NewContext(), ast.Floor, types.NewFieldType(mysql.TypeLonglong), decimalColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_FloorDecToDec
|
|
function, err = NewFunction(mock.NewContext(), ast.Floor, types.NewFieldType(mysql.TypeNewDecimal), decimalColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_Log1Arg
|
|
function, err = NewFunction(mock.NewContext(), ast.Log, types.NewFieldType(mysql.TypeDouble), realColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_Log2Args
|
|
function, err = NewFunction(mock.NewContext(), ast.Log, types.NewFieldType(mysql.TypeDouble), realColumn, realColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_Log2
|
|
function, err = NewFunction(mock.NewContext(), ast.Log2, types.NewFieldType(mysql.TypeDouble), realColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_Log10
|
|
function, err = NewFunction(mock.NewContext(), ast.Log10, types.NewFieldType(mysql.TypeDouble), realColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_Exp
|
|
function, err = NewFunction(mock.NewContext(), ast.Exp, types.NewFieldType(mysql.TypeDouble), realColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_Pow
|
|
function, err = NewFunction(mock.NewContext(), ast.Pow, types.NewFieldType(mysql.TypeDouble), realColumn, realColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_Pow, Power is a synonym for Pow
|
|
function, err = NewFunction(mock.NewContext(), ast.Power, types.NewFieldType(mysql.TypeDouble), realColumn, realColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_Radians
|
|
function, err = NewFunction(mock.NewContext(), ast.Radians, types.NewFieldType(mysql.TypeDouble), realColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_Degrees
|
|
function, err = NewFunction(mock.NewContext(), ast.Degrees, types.NewFieldType(mysql.TypeDouble), realColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_CRC32
|
|
function, err = NewFunction(mock.NewContext(), ast.CRC32, types.NewFieldType(mysql.TypeLonglong), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_Conv
|
|
function, err = NewFunction(mock.NewContext(), ast.Conv, types.NewFieldType(mysql.TypeDouble), stringColumn, intColumn, intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// Replace
|
|
function, err = NewFunction(mock.NewContext(), ast.Replace, types.NewFieldType(mysql.TypeString), stringColumn, stringColumn, stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// InetAton
|
|
function, err = NewFunction(mock.NewContext(), ast.InetAton, types.NewFieldType(mysql.TypeString), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// InetNtoa
|
|
function, err = NewFunction(mock.NewContext(), ast.InetNtoa, types.NewFieldType(mysql.TypeLonglong), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// Inet6Aton
|
|
function, err = NewFunction(mock.NewContext(), ast.Inet6Aton, types.NewFieldType(mysql.TypeString), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// Inet6Ntoa
|
|
function, err = NewFunction(mock.NewContext(), ast.Inet6Ntoa, types.NewFieldType(mysql.TypeLonglong), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_RoundReal
|
|
function, err = NewFunction(mock.NewContext(), ast.Round, types.NewFieldType(mysql.TypeDouble), realColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_RoundInt
|
|
function, err = NewFunction(mock.NewContext(), ast.Round, types.NewFieldType(mysql.TypeLonglong), intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_RoundDecimal
|
|
function, err = NewFunction(mock.NewContext(), ast.Round, types.NewFieldType(mysql.TypeNewDecimal), decimalColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_RoundWithFracReal
|
|
function, err = NewFunction(mock.NewContext(), ast.Round, types.NewFieldType(mysql.TypeDouble), realColumn, intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_RoundWithFracInt
|
|
function, err = NewFunction(mock.NewContext(), ast.Round, types.NewFieldType(mysql.TypeLonglong), intColumn, intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_RoundWithFracDecimal
|
|
function, err = NewFunction(mock.NewContext(), ast.Round, types.NewFieldType(mysql.TypeNewDecimal), decimalColumn, intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// concat
|
|
function, err = NewFunction(mock.NewContext(), ast.Concat, types.NewFieldType(mysql.TypeString), stringColumn, intColumn, realColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// UnixTimestampCurrent
|
|
function, err = NewFunction(mock.NewContext(), ast.UnixTimestamp, types.NewFieldType(mysql.TypeLonglong))
|
|
require.NoError(t, err)
|
|
_, ok := function.(*Constant)
|
|
require.True(t, ok)
|
|
|
|
// UnixTimestampInt
|
|
datetimeColumn.RetType.SetDecimal(0)
|
|
function, err = NewFunction(mock.NewContext(), ast.UnixTimestamp, types.NewFieldType(mysql.TypeLonglong), datetimeColumn)
|
|
require.NoError(t, err)
|
|
require.Equal(t, tipb.ScalarFuncSig_UnixTimestampInt, function.(*ScalarFunction).Function.PbCode())
|
|
exprs = append(exprs, function)
|
|
|
|
// UnixTimestampDecimal
|
|
datetimeColumn.RetType.SetDecimal(types.UnspecifiedLength)
|
|
function, err = NewFunction(mock.NewContext(), ast.UnixTimestamp, types.NewFieldType(mysql.TypeNewDecimal), datetimeColumn)
|
|
require.NoError(t, err)
|
|
require.Equal(t, tipb.ScalarFuncSig_UnixTimestampDec, function.(*ScalarFunction).Function.PbCode())
|
|
exprs = append(exprs, function)
|
|
|
|
// Year
|
|
function, err = NewFunction(mock.NewContext(), ast.Year, types.NewFieldType(mysql.TypeLonglong), datetimeColumn)
|
|
require.NoError(t, err)
|
|
require.Equal(t, tipb.ScalarFuncSig_Year, function.(*ScalarFunction).Function.PbCode())
|
|
exprs = append(exprs, function)
|
|
|
|
// Day
|
|
function, err = NewFunction(mock.NewContext(), ast.Day, types.NewFieldType(mysql.TypeLonglong), datetimeColumn)
|
|
require.NoError(t, err)
|
|
require.Equal(t, tipb.ScalarFuncSig_DayOfMonth, function.(*ScalarFunction).Function.PbCode())
|
|
exprs = append(exprs, function)
|
|
|
|
// Repeat
|
|
function, err = NewFunction(mock.NewContext(), ast.Repeat, types.NewFieldType(mysql.TypeString), stringColumn, intColumn)
|
|
require.NoError(t, err)
|
|
require.Equal(t, tipb.ScalarFuncSig_Repeat, function.(*ScalarFunction).Function.PbCode())
|
|
exprs = append(exprs, function)
|
|
|
|
// Datediff
|
|
function, err = NewFunction(mock.NewContext(), ast.DateDiff, types.NewFieldType(mysql.TypeLonglong), datetimeColumn, datetimeColumn)
|
|
require.NoError(t, err)
|
|
require.Equal(t, tipb.ScalarFuncSig_DateDiff, function.(*ScalarFunction).Function.PbCode())
|
|
exprs = append(exprs, function)
|
|
|
|
// Datesub
|
|
constStringColumn := new(Constant)
|
|
constStringColumn.Value = types.NewStringDatum("day")
|
|
constStringColumn.RetType = types.NewFieldType(mysql.TypeString)
|
|
function, err = NewFunction(mock.NewContext(), ast.DateSub, types.NewFieldType(mysql.TypeDatetime), datetimeColumn, intColumn, constStringColumn)
|
|
require.NoError(t, err)
|
|
require.Equal(t, tipb.ScalarFuncSig_SubDateDatetimeInt, function.(*ScalarFunction).Function.PbCode())
|
|
exprs = append(exprs, function)
|
|
function, err = NewFunction(mock.NewContext(), ast.DateSub, types.NewFieldType(mysql.TypeDatetime), stringColumn, intColumn, constStringColumn)
|
|
require.NoError(t, err)
|
|
require.Equal(t, tipb.ScalarFuncSig_SubDateStringInt, function.(*ScalarFunction).Function.PbCode())
|
|
exprs = append(exprs, function)
|
|
function, err = NewFunction(mock.NewContext(), ast.SubDate, types.NewFieldType(mysql.TypeDatetime), datetimeColumn, intColumn, constStringColumn)
|
|
require.NoError(t, err)
|
|
require.Equal(t, tipb.ScalarFuncSig_SubDateDatetimeInt, function.(*ScalarFunction).Function.PbCode())
|
|
exprs = append(exprs, function)
|
|
|
|
// castTimeAsString:
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeString), datetimeColumn)
|
|
require.NoError(t, err)
|
|
require.Equal(t, tipb.ScalarFuncSig_CastTimeAsString, function.(*ScalarFunction).Function.PbCode())
|
|
exprs = append(exprs, function)
|
|
|
|
// concat_ws
|
|
function, err = NewFunction(mock.NewContext(), ast.ConcatWS, types.NewFieldType(mysql.TypeString), stringColumn, stringColumn, stringColumn)
|
|
require.NoError(t, err)
|
|
require.Equal(t, tipb.ScalarFuncSig_ConcatWS, function.(*ScalarFunction).Function.PbCode())
|
|
exprs = append(exprs, function)
|
|
|
|
function, err = NewFunction(mock.NewContext(), ast.FromDays, types.NewFieldType(mysql.TypeDate), intColumn)
|
|
require.NoError(t, err)
|
|
require.Equal(t, tipb.ScalarFuncSig_FromDays, function.(*ScalarFunction).Function.PbCode())
|
|
exprs = append(exprs, function)
|
|
|
|
function, err = NewFunction(mock.NewContext(), ast.ToDays, types.NewFieldType(mysql.TypeLonglong), datetimeColumn)
|
|
require.NoError(t, err)
|
|
require.Equal(t, tipb.ScalarFuncSig_ToDays, function.(*ScalarFunction).Function.PbCode())
|
|
exprs = append(exprs, function)
|
|
|
|
// StrToDateDateTime
|
|
function, err = NewFunction(mock.NewContext(), ast.StrToDate, types.NewFieldType(mysql.TypeDatetime), stringColumn, stringColumn)
|
|
require.NoError(t, err)
|
|
require.Equal(t, tipb.ScalarFuncSig_StrToDateDatetime, function.(*ScalarFunction).Function.PbCode())
|
|
exprs = append(exprs, function)
|
|
|
|
// cast Int32 to Int32
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeLong), int32Column)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// cast float32 to float32
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeFloat), float32Column)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// upper string
|
|
function, err = NewFunction(mock.NewContext(), ast.Upper, types.NewFieldType(mysql.TypeString), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ucase string
|
|
function, err = NewFunction(mock.NewContext(), ast.Ucase, types.NewFieldType(mysql.TypeString), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// lower string
|
|
function, err = NewFunction(mock.NewContext(), ast.Lower, types.NewFieldType(mysql.TypeString), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// lcase string
|
|
function, err = NewFunction(mock.NewContext(), ast.Lcase, types.NewFieldType(mysql.TypeString), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// sysdate
|
|
function, err = NewFunction(mock.NewContext(), ast.Sysdate, types.NewFieldType(mysql.TypeDatetime), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
canPush := CanExprsPushDown(pushDownCtx, exprs, kv.TiFlash)
|
|
require.Equal(t, true, canPush)
|
|
|
|
exprs = exprs[:0]
|
|
|
|
// Substring2Args: can not be pushed
|
|
function, err = NewFunction(mock.NewContext(), ast.Substr, types.NewFieldType(mysql.TypeString), binaryStringColumn, intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// Substring3Args: can not be pushed
|
|
function, err = NewFunction(mock.NewContext(), ast.Substr, types.NewFieldType(mysql.TypeString), binaryStringColumn, intColumn, intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ExtractDatetimeFromString: can not be pushed
|
|
extractDatetimeFromStringUnitCol := new(Constant)
|
|
extractDatetimeFromStringUnitCol.Value = types.NewStringDatum("day_microsecond")
|
|
extractDatetimeFromStringUnitCol.RetType = types.NewFieldType(mysql.TypeString)
|
|
function, err = NewFunction(mock.NewContext(), ast.Extract, types.NewFieldType(mysql.TypeLonglong), extractDatetimeFromStringUnitCol, stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// Cast to Int32: not supported
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeLong), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// Cast to Float: not supported
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeFloat), intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// Cast to invalid decimal Type: not supported
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeNewDecimal), intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// cast Int32 to UInt32
|
|
unsignedInt32Type := types.NewFieldType(mysql.TypeLong)
|
|
unsignedInt32Type.SetFlag(mysql.UnsignedFlag)
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, unsignedInt32Type, int32Column)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// cast Enum as String : not supported
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeString), enumColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
pushed, remained := PushDownExprs(pushDownCtx, exprs, kv.TiFlash)
|
|
require.Len(t, pushed, 0)
|
|
require.Len(t, remained, len(exprs))
|
|
|
|
pushed, remained = PushDownExprsWithExtraInfo(pushDownCtx, exprs, kv.TiFlash, true)
|
|
require.Len(t, pushed, 0)
|
|
require.Len(t, remained, len(exprs))
|
|
|
|
exprs = exprs[:0]
|
|
// cast Enum as UInt : supported
|
|
unsignedInt := types.NewFieldType(mysql.TypeLonglong)
|
|
unsignedInt.SetFlag(mysql.UnsignedFlag)
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, unsignedInt, enumColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// cast Enum as Int : supported
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeLonglong), enumColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// cast Enum as Double : supported
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeDouble), enumColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// cast Enum as decimal : supported
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, validDecimalType, enumColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// quarter: supported
|
|
function, err = NewFunction(mock.NewContext(), ast.Quarter, types.NewFieldType(mysql.TypeLonglong), datetimeColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// strcmp
|
|
function, err = NewFunction(mock.NewContext(), ast.Strcmp, types.NewFieldType(mysql.TypeLonglong), stringColumn, stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// DayName: supported
|
|
function, err = NewFunction(mock.NewContext(), ast.DayName, types.NewFieldType(mysql.TypeString), datetimeColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// MonthName: supported
|
|
function, err = NewFunction(mock.NewContext(), ast.MonthName, types.NewFieldType(mysql.TypeString), datetimeColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ToSeconds: supported
|
|
function, err = NewFunction(mock.NewContext(), ast.ToSeconds, types.NewFieldType(mysql.TypeLonglong), datetimeColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// regexpUTF8: supported
|
|
function, err = NewFunction(mock.NewContext(), ast.Regexp, types.NewFieldType(mysql.TypeLonglong), stringColumn, stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// regexp: supported
|
|
function, err = NewFunction(mock.NewContext(), ast.Regexp, types.NewFieldType(mysql.TypeLonglong), binaryStringColumn, binaryStringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// regexp_like: supported
|
|
function, err = NewFunction(mock.NewContext(), ast.RegexpLike, types.NewFieldType(mysql.TypeLonglong), binaryStringColumn, binaryStringColumn, binaryStringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// regexp_instr: supported
|
|
function, err = NewFunction(mock.NewContext(), ast.RegexpInStr, types.NewFieldType(mysql.TypeLonglong), stringColumn, stringColumn, intColumn, intColumn, intColumn, stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// regexp_substr: supported
|
|
function, err = NewFunction(mock.NewContext(), ast.RegexpSubstr, types.NewFieldType(mysql.TypeString), stringColumn, stringColumn, intColumn, intColumn, stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// regexp_replace: supported
|
|
function, err = NewFunction(mock.NewContext(), ast.RegexpReplace, types.NewFieldType(mysql.TypeString), stringColumn, stringColumn, stringColumn, intColumn, intColumn, stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ilike: supported
|
|
function, err = NewFunction(mock.NewContext(), ast.Ilike, types.NewFieldType(mysql.TypeLonglong), stringColumn, stringColumn, stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// greatest
|
|
function, err = NewFunction(mock.NewContext(), ast.Greatest, types.NewFieldType(mysql.TypeLonglong), int32Column, intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
function, err = NewFunction(mock.NewContext(), ast.Greatest, types.NewFieldType(mysql.TypeDouble), float32Column, intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
function, err = NewFunction(mock.NewContext(), ast.Greatest, types.NewFieldType(mysql.TypeString), stringColumn, stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// least
|
|
function, err = NewFunction(mock.NewContext(), ast.Least, types.NewFieldType(mysql.TypeLonglong), int32Column, intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
function, err = NewFunction(mock.NewContext(), ast.Least, types.NewFieldType(mysql.TypeDouble), float32Column, intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
function, err = NewFunction(mock.NewContext(), ast.Least, types.NewFieldType(mysql.TypeString), stringColumn, stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// is true
|
|
function, err = NewFunction(mock.NewContext(), ast.IsTruthWithoutNull, types.NewFieldType(mysql.TypeLonglong), int32Column)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
function, err = NewFunction(mock.NewContext(), ast.IsTruthWithoutNull, types.NewFieldType(mysql.TypeLonglong), float32Column)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
function, err = NewFunction(mock.NewContext(), ast.IsTruthWithoutNull, types.NewFieldType(mysql.TypeLonglong), decimalColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
// is true with null
|
|
function, err = NewFunction(mock.NewContext(), ast.IsTruthWithNull, types.NewFieldType(mysql.TypeLonglong), int32Column)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
function, err = NewFunction(mock.NewContext(), ast.IsTruthWithNull, types.NewFieldType(mysql.TypeLonglong), float32Column)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
function, err = NewFunction(mock.NewContext(), ast.IsTruthWithNull, types.NewFieldType(mysql.TypeLonglong), decimalColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
// is false, note seems there is actually no is_false_with_null, so unable to add ut for it
|
|
function, err = NewFunction(mock.NewContext(), ast.IsFalsity, types.NewFieldType(mysql.TypeLonglong), int32Column)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
function, err = NewFunction(mock.NewContext(), ast.IsFalsity, types.NewFieldType(mysql.TypeLonglong), float32Column)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
function, err = NewFunction(mock.NewContext(), ast.IsFalsity, types.NewFieldType(mysql.TypeLonglong), decimalColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// DayOfWeek
|
|
function, err = NewFunction(mock.NewContext(), ast.DayOfWeek, types.NewFieldType(mysql.TypeDatetime), datetimeColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// DayOfMonth
|
|
function, err = NewFunction(mock.NewContext(), ast.DayOfMonth, types.NewFieldType(mysql.TypeDatetime), datetimeColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// DayOfYear
|
|
function, err = NewFunction(mock.NewContext(), ast.DayOfYear, types.NewFieldType(mysql.TypeDatetime), datetimeColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// LastDay
|
|
function, err = NewFunction(mock.NewContext(), ast.LastDay, types.NewFieldType(mysql.TypeDatetime), datetimeColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// WeekOfYear
|
|
function, err = NewFunction(mock.NewContext(), ast.WeekOfYear, types.NewFieldType(mysql.TypeDatetime), datetimeColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// TimeToSec
|
|
function, err = NewFunction(mock.NewContext(), ast.TimeToSec, types.NewFieldType(mysql.TypeDuration), durationColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_RightShift
|
|
function, err = NewFunction(mock.NewContext(), ast.RightShift, types.NewFieldType(mysql.TypeLonglong), intColumn, intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ScalarFuncSig_LeftShift
|
|
function, err = NewFunction(mock.NewContext(), ast.LeftShift, types.NewFieldType(mysql.TypeLonglong), intColumn, intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// ReverseUTF8
|
|
function, err = NewFunction(mock.NewContext(), ast.Reverse, types.NewFieldType(mysql.TypeString), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// Reverse
|
|
function, err = NewFunction(mock.NewContext(), ast.Reverse, types.NewFieldType(mysql.TypeBlob), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// space
|
|
function, err = NewFunction(mock.NewContext(), ast.Space, types.NewFieldType(mysql.TypeLonglong), int32Column)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// HexStr
|
|
function, err = NewFunction(mock.NewContext(), ast.Hex, types.NewFieldType(mysql.TypeString), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// HexInt
|
|
function, err = NewFunction(mock.NewContext(), ast.Hex, types.NewFieldType(mysql.TypeString), intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// Bin
|
|
function, err = NewFunction(mock.NewContext(), ast.Bin, types.NewFieldType(mysql.TypeString), intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// Elt
|
|
function, err = NewFunction(mock.NewContext(), ast.Elt, types.NewFieldType(mysql.TypeString), intColumn, stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastTimeAsDuration
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeDuration), datetimeColumn)
|
|
require.NoError(t, err)
|
|
require.Equal(t, tipb.ScalarFuncSig_CastTimeAsDuration, function.(*ScalarFunction).Function.PbCode())
|
|
exprs = append(exprs, function)
|
|
|
|
// Unhex
|
|
function, err = NewFunction(mock.NewContext(), ast.Unhex, types.NewFieldType(mysql.TypeString), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// IsIPv4
|
|
function, err = NewFunction(mock.NewContext(), ast.IsIPv4, types.NewFieldType(mysql.TypeString), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// IsIPv6
|
|
function, err = NewFunction(mock.NewContext(), ast.IsIPv6, types.NewFieldType(mysql.TypeString), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// Grouping
|
|
init := func(groupingFunc *ScalarFunction) (*ScalarFunction, error) {
|
|
var err error
|
|
if groupingFunc.FuncName.L == ast.Grouping {
|
|
err = groupingFunc.Function.(*BuiltinGroupingImplSig).
|
|
SetMetadata(tipb.GroupingMode_ModeBitAnd, []map[uint64]struct{}{})
|
|
}
|
|
return groupingFunc, err
|
|
}
|
|
function, err = NewFunctionWithInit(mock.NewContext(), ast.Grouping, types.NewFieldType(mysql.TypeLonglong), init, uintColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastIntAsJson
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeJSON), intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastRealAsJson
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeJSON), realColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastDecimalAsJson
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeJSON), decimalColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastStringAsJson
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeJSON), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeJSON), binaryStringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastTimeAsJson
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeJSON), datetimeColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
// CastDurationAsJson
|
|
function, err = NewFunction(mock.NewContext(), ast.Cast, types.NewFieldType(mysql.TypeJSON), durationColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
pushed, remained = PushDownExprs(pushDownCtx, exprs, kv.TiFlash)
|
|
require.Len(t, pushed, len(exprs))
|
|
require.Len(t, remained, 0)
|
|
|
|
pushed, remained = PushDownExprsWithExtraInfo(pushDownCtx, exprs, kv.TiFlash, true)
|
|
require.Len(t, pushed, len(exprs))
|
|
require.Len(t, remained, 0)
|
|
}
|
|
|
|
func TestExprOnlyPushDownToFlash(t *testing.T) {
|
|
t.Skip("Skip this unstable test temporarily and bring it back before 2021-07-26")
|
|
client := new(mock.Client)
|
|
|
|
exprs := make([]Expression, 0)
|
|
|
|
//jsonColumn := genColumn(mysql.TypeJSON, 1)
|
|
intColumn := genColumn(mysql.TypeLonglong, 2)
|
|
//realColumn := genColumn(mysql.TypeDouble, 3)
|
|
decimalColumn := genColumn(mysql.TypeNewDecimal, 4)
|
|
stringColumn := genColumn(mysql.TypeString, 5)
|
|
datetimeColumn := genColumn(mysql.TypeDatetime, 6)
|
|
binaryStringColumn := genColumn(mysql.TypeString, 7)
|
|
binaryStringColumn.RetType.SetCollate(charset.CollationBin)
|
|
|
|
function, err := NewFunction(mock.NewContext(), ast.Substr, types.NewFieldType(mysql.TypeString), stringColumn, intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
function, err = NewFunction(mock.NewContext(), ast.Substring, types.NewFieldType(mysql.TypeString), stringColumn, intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
function, err = NewFunction(mock.NewContext(), ast.GetFormat, types.NewFieldType(mysql.TypeString), stringColumn, stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
function, err = NewFunction(mock.NewContext(), ast.TimestampDiff, types.NewFieldType(mysql.TypeLonglong), stringColumn, datetimeColumn, datetimeColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
function, err = NewFunction(mock.NewContext(), ast.FromUnixTime, types.NewFieldType(mysql.TypeDatetime), decimalColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
function, err = NewFunction(mock.NewContext(), ast.Extract, types.NewFieldType(mysql.TypeLonglong), stringColumn, datetimeColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
ctx := mock.NewContext()
|
|
pushDownCtx := NewPushDownContextFromSessionVars(ctx, ctx.GetSessionVars(), client)
|
|
pushed, remained := PushDownExprs(pushDownCtx, exprs, kv.UnSpecified)
|
|
require.Len(t, pushed, len(exprs))
|
|
require.Len(t, remained, 0)
|
|
|
|
canPush := CanExprsPushDown(pushDownCtx, exprs, kv.TiFlash)
|
|
require.Equal(t, true, canPush)
|
|
canPush = CanExprsPushDown(pushDownCtx, exprs, kv.TiKV)
|
|
require.Equal(t, false, canPush)
|
|
|
|
pushed, remained = PushDownExprs(pushDownCtx, exprs, kv.TiFlash)
|
|
require.Len(t, pushed, len(exprs))
|
|
require.Len(t, remained, 0)
|
|
|
|
pushed, remained = PushDownExprs(pushDownCtx, exprs, kv.TiKV)
|
|
require.Len(t, pushed, 0)
|
|
require.Len(t, remained, len(exprs))
|
|
}
|
|
|
|
func TestExprPushDownToTiKV(t *testing.T) {
|
|
client := new(mock.Client)
|
|
|
|
exprs := make([]Expression, 0)
|
|
|
|
jsonColumn := genColumn(mysql.TypeJSON, 1)
|
|
intColumn := genColumn(mysql.TypeLonglong, 2)
|
|
realColumn := genColumn(mysql.TypeDouble, 3)
|
|
decimalColumn := genColumn(mysql.TypeNewDecimal, 4)
|
|
stringColumn := genColumn(mysql.TypeString, 5)
|
|
datetimeColumn := genColumn(mysql.TypeDatetime, 6)
|
|
binaryStringColumn := genColumn(mysql.TypeString, 7)
|
|
dateColumn := genColumn(mysql.TypeDate, 8)
|
|
byteColumn := genColumn(mysql.TypeBit, 9)
|
|
durationColumn := genColumn(mysql.TypeDuration, 10)
|
|
binaryStringColumn.RetType.SetCollate(charset.CollationBin)
|
|
|
|
// Test exprs that cannot be pushed.
|
|
function, err := NewFunction(mock.NewContext(), ast.InetAton, types.NewFieldType(mysql.TypeString), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
function, err = NewFunction(mock.NewContext(), ast.InetNtoa, types.NewFieldType(mysql.TypeLonglong), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
function, err = NewFunction(mock.NewContext(), ast.Inet6Aton, types.NewFieldType(mysql.TypeString), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
function, err = NewFunction(mock.NewContext(), ast.Inet6Ntoa, types.NewFieldType(mysql.TypeLonglong), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
function, err = NewFunction(mock.NewContext(), ast.IsIPv4, types.NewFieldType(mysql.TypeString), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
function, err = NewFunction(mock.NewContext(), ast.IsIPv6, types.NewFieldType(mysql.TypeString), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
function, err = NewFunction(mock.NewContext(), ast.IsIPv4Compat, types.NewFieldType(mysql.TypeString), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
function, err = NewFunction(mock.NewContext(), ast.IsIPv4Mapped, types.NewFieldType(mysql.TypeString), stringColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
|
|
ctx := mock.NewContext()
|
|
pushDownCtx := NewPushDownContextFromSessionVars(ctx, ctx.GetSessionVars(), client)
|
|
pushed, remained := PushDownExprs(pushDownCtx, exprs, kv.TiKV)
|
|
require.Len(t, pushed, 0)
|
|
require.Len(t, remained, len(exprs))
|
|
|
|
// Test Conv function, `conv` function for a BIT column should not be pushed down for its special behavior which
|
|
// is only handled in TiDB currently.
|
|
// see issue: https://github.com/pingcap/tidb/issues/51877
|
|
exprs = exprs[:0]
|
|
function, err = NewFunction(mock.NewContext(), ast.Conv, types.NewFieldType(mysql.TypeString), stringColumn, intColumn, intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
pushed, remained = PushDownExprs(pushDownCtx, exprs, kv.TiKV)
|
|
require.Len(t, pushed, len(exprs))
|
|
require.Len(t, remained, 0)
|
|
exprs = exprs[:0]
|
|
// when conv a column with type BIT, a cast function will be used to cast bit to a binary string
|
|
castTp := types.NewFieldType(mysql.TypeString)
|
|
castTp.SetCharset(charset.CharsetBin)
|
|
castTp.SetCollate(charset.CollationBin)
|
|
castByteAsStringFunc, err := NewFunction(mock.NewContext(), ast.Cast, castTp, byteColumn)
|
|
require.NoError(t, err)
|
|
function, err = NewFunction(mock.NewContext(), ast.Conv, types.NewFieldType(mysql.TypeString), castByteAsStringFunc, intColumn, intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
pushed, remained = PushDownExprs(pushDownCtx, exprs, kv.TiKV)
|
|
require.Len(t, pushed, 0)
|
|
require.Len(t, remained, len(exprs))
|
|
|
|
// Test exprs that can be pushed.
|
|
exprs = exprs[:0]
|
|
pushed = pushed[:0]
|
|
remained = remained[:0]
|
|
|
|
substringRelated := []string{ast.Substr, ast.Substring, ast.Mid}
|
|
for _, exprName := range substringRelated {
|
|
function, err = NewFunction(ctx, exprName, types.NewFieldType(mysql.TypeString), stringColumn, intColumn, intColumn)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
}
|
|
|
|
testcases := []struct {
|
|
functionName string
|
|
retType *types.FieldType
|
|
args []Expression
|
|
}{
|
|
{
|
|
functionName: ast.CharLength,
|
|
retType: types.NewFieldType(mysql.TypeString),
|
|
args: []Expression{stringColumn},
|
|
},
|
|
{
|
|
functionName: ast.Sin,
|
|
retType: types.NewFieldType(mysql.TypeDouble),
|
|
args: []Expression{intColumn},
|
|
},
|
|
{
|
|
functionName: ast.Asin,
|
|
retType: types.NewFieldType(mysql.TypeDouble),
|
|
args: []Expression{intColumn},
|
|
},
|
|
{
|
|
functionName: ast.Cos,
|
|
retType: types.NewFieldType(mysql.TypeDouble),
|
|
args: []Expression{intColumn},
|
|
},
|
|
{
|
|
functionName: ast.Acos,
|
|
retType: types.NewFieldType(mysql.TypeDouble),
|
|
args: []Expression{intColumn},
|
|
},
|
|
{
|
|
functionName: ast.Atan,
|
|
retType: types.NewFieldType(mysql.TypeDouble),
|
|
args: []Expression{intColumn},
|
|
},
|
|
{
|
|
functionName: ast.Cot,
|
|
retType: types.NewFieldType(mysql.TypeDouble),
|
|
args: []Expression{intColumn},
|
|
},
|
|
{
|
|
functionName: ast.Atan2,
|
|
retType: types.NewFieldType(mysql.TypeDouble),
|
|
args: []Expression{intColumn, intColumn},
|
|
},
|
|
{
|
|
functionName: ast.DateFormat,
|
|
retType: types.NewFieldType(mysql.TypeDate),
|
|
args: []Expression{dateColumn, stringColumn},
|
|
},
|
|
{
|
|
functionName: ast.Hour,
|
|
retType: types.NewFieldType(mysql.TypeDate),
|
|
args: []Expression{dateColumn},
|
|
},
|
|
{
|
|
functionName: ast.Minute,
|
|
retType: types.NewFieldType(mysql.TypeDate),
|
|
args: []Expression{dateColumn},
|
|
},
|
|
{
|
|
functionName: ast.Second,
|
|
retType: types.NewFieldType(mysql.TypeDate),
|
|
args: []Expression{dateColumn},
|
|
},
|
|
{
|
|
functionName: ast.Month,
|
|
retType: types.NewFieldType(mysql.TypeDate),
|
|
args: []Expression{dateColumn},
|
|
},
|
|
{
|
|
functionName: ast.MicroSecond,
|
|
retType: types.NewFieldType(mysql.TypeDate),
|
|
args: []Expression{dateColumn},
|
|
},
|
|
{
|
|
functionName: ast.PI,
|
|
retType: types.NewFieldType(mysql.TypeDouble),
|
|
args: []Expression{},
|
|
},
|
|
{
|
|
functionName: ast.Round,
|
|
retType: types.NewFieldType(mysql.TypeDouble),
|
|
args: []Expression{intColumn},
|
|
},
|
|
//{
|
|
// functionName: ast.Truncate,
|
|
// retType: types.NewFieldType(mysql.TypeDouble),
|
|
// args: []Expression{intColumn, intColumn},
|
|
//},
|
|
{
|
|
functionName: ast.Date,
|
|
retType: types.NewFieldType(mysql.TypeDate),
|
|
args: []Expression{dateColumn},
|
|
},
|
|
{
|
|
functionName: ast.Week,
|
|
retType: types.NewFieldType(mysql.TypeDate),
|
|
args: []Expression{dateColumn},
|
|
},
|
|
{
|
|
functionName: ast.DateDiff,
|
|
retType: types.NewFieldType(mysql.TypeDate),
|
|
args: []Expression{dateColumn, dateColumn},
|
|
},
|
|
{
|
|
functionName: ast.Mod,
|
|
retType: types.NewFieldType(mysql.TypeInt24),
|
|
args: []Expression{intColumn, intColumn},
|
|
},
|
|
{
|
|
functionName: ast.Upper,
|
|
retType: types.NewFieldType(mysql.TypeString),
|
|
args: []Expression{stringColumn},
|
|
},
|
|
{
|
|
functionName: ast.Lower,
|
|
retType: types.NewFieldType(mysql.TypeString),
|
|
args: []Expression{stringColumn},
|
|
},
|
|
{
|
|
functionName: ast.Pow,
|
|
retType: types.NewFieldType(mysql.TypeDouble),
|
|
args: []Expression{realColumn, realColumn},
|
|
},
|
|
{
|
|
functionName: ast.Power,
|
|
retType: types.NewFieldType(mysql.TypeDouble),
|
|
args: []Expression{realColumn, realColumn},
|
|
},
|
|
{
|
|
functionName: ast.JSONReplace,
|
|
retType: types.NewFieldType(mysql.TypeJSON),
|
|
args: []Expression{jsonColumn, stringColumn, jsonColumn, stringColumn, jsonColumn},
|
|
},
|
|
{
|
|
functionName: ast.JSONArrayAppend,
|
|
retType: types.NewFieldType(mysql.TypeJSON),
|
|
args: []Expression{jsonColumn, stringColumn, jsonColumn, stringColumn, jsonColumn},
|
|
},
|
|
{
|
|
functionName: ast.JSONMergePatch,
|
|
retType: types.NewFieldType(mysql.TypeJSON),
|
|
args: []Expression{jsonColumn, jsonColumn, jsonColumn},
|
|
},
|
|
{
|
|
functionName: ast.DateAdd,
|
|
retType: types.NewFieldType(mysql.TypeString),
|
|
args: []Expression{stringColumn, stringColumn, NewStrConst("second")},
|
|
},
|
|
{
|
|
functionName: ast.DateAdd,
|
|
retType: types.NewFieldType(mysql.TypeString),
|
|
args: []Expression{decimalColumn, realColumn, NewStrConst("day")},
|
|
},
|
|
{
|
|
functionName: ast.DateAdd,
|
|
retType: types.NewFieldType(mysql.TypeDatetime),
|
|
args: []Expression{datetimeColumn, intColumn, NewStrConst("year")},
|
|
},
|
|
{
|
|
functionName: ast.DateAdd,
|
|
retType: types.NewFieldType(mysql.TypeDuration),
|
|
args: []Expression{durationColumn, stringColumn, NewStrConst("minute")},
|
|
},
|
|
{
|
|
functionName: ast.DateAdd,
|
|
retType: types.NewFieldType(mysql.TypeDatetime),
|
|
args: []Expression{durationColumn, stringColumn, NewStrConst("year_month")},
|
|
},
|
|
{
|
|
functionName: ast.DateSub,
|
|
retType: types.NewFieldType(mysql.TypeString),
|
|
args: []Expression{stringColumn, intColumn, NewStrConst("microsecond")},
|
|
},
|
|
{
|
|
functionName: ast.DateSub,
|
|
retType: types.NewFieldType(mysql.TypeString),
|
|
args: []Expression{intColumn, realColumn, NewStrConst("day")},
|
|
},
|
|
{
|
|
functionName: ast.DateSub,
|
|
retType: types.NewFieldType(mysql.TypeDatetime),
|
|
args: []Expression{datetimeColumn, intColumn, NewStrConst("quarter")},
|
|
},
|
|
{
|
|
functionName: ast.DateSub,
|
|
retType: types.NewFieldType(mysql.TypeDuration),
|
|
args: []Expression{durationColumn, stringColumn, NewStrConst("hour")},
|
|
},
|
|
{
|
|
functionName: ast.DateSub,
|
|
retType: types.NewFieldType(mysql.TypeDatetime),
|
|
args: []Expression{durationColumn, stringColumn, NewStrConst("year_month")},
|
|
},
|
|
{
|
|
functionName: ast.AddDate,
|
|
retType: types.NewFieldType(mysql.TypeDatetime),
|
|
args: []Expression{durationColumn, stringColumn, NewStrConst("WEEK")},
|
|
},
|
|
{
|
|
functionName: ast.SubDate,
|
|
retType: types.NewFieldType(mysql.TypeString),
|
|
args: []Expression{stringColumn, intColumn, NewStrConst("hour")},
|
|
},
|
|
{
|
|
functionName: ast.FromUnixTime,
|
|
retType: types.NewFieldType(mysql.TypeDatetime),
|
|
args: []Expression{decimalColumn},
|
|
},
|
|
{
|
|
functionName: ast.FromUnixTime,
|
|
retType: types.NewFieldType(mysql.TypeString),
|
|
args: []Expression{decimalColumn, stringColumn},
|
|
},
|
|
//{
|
|
// functionName: ast.StrToDate,
|
|
// retType: types.NewFieldType(mysql.TypeDatetime),
|
|
// args: []Expression{stringColumn, stringColumn},
|
|
//},
|
|
//{
|
|
// functionName: ast.StrToDate,
|
|
// retType: types.NewFieldType(mysql.TypeDuration),
|
|
// args: []Expression{stringColumn, NewStrConst("%h")},
|
|
//},
|
|
//{
|
|
// functionName: ast.StrToDate,
|
|
// retType: types.NewFieldType(mysql.TypeDate),
|
|
// args: []Expression{stringColumn, NewStrConst("%y")},
|
|
//},
|
|
//{
|
|
// functionName: ast.StrToDate,
|
|
// retType: types.NewFieldType(mysql.TypeDatetime),
|
|
// args: []Expression{stringColumn, NewStrConst("%h%y")},
|
|
//},
|
|
{
|
|
functionName: ast.TimestampDiff,
|
|
retType: types.NewFieldType(mysql.TypeLong),
|
|
args: []Expression{NewStrConst("Second"), datetimeColumn, datetimeColumn},
|
|
},
|
|
{
|
|
functionName: ast.TimestampDiff,
|
|
retType: types.NewFieldType(mysql.TypeLong),
|
|
args: []Expression{NewStrConst("DAY"), datetimeColumn, datetimeColumn},
|
|
},
|
|
{
|
|
functionName: ast.TimestampDiff,
|
|
retType: types.NewFieldType(mysql.TypeLong),
|
|
args: []Expression{NewStrConst("year"), datetimeColumn, datetimeColumn},
|
|
},
|
|
{
|
|
functionName: ast.UnixTimestamp,
|
|
retType: types.NewFieldType(mysql.TypeLong),
|
|
args: []Expression{datetimeColumn},
|
|
},
|
|
{
|
|
functionName: ast.UnixTimestamp,
|
|
retType: types.NewFieldType(mysql.TypeNewDecimal),
|
|
args: []Expression{stringColumn},
|
|
},
|
|
}
|
|
|
|
ctx = mock.NewContext()
|
|
pushDownCtx = NewPushDownContextFromSessionVars(ctx, ctx.GetSessionVars(), client)
|
|
for _, tc := range testcases {
|
|
function, err = NewFunction(ctx, tc.functionName, tc.retType, tc.args...)
|
|
require.NoError(t, err)
|
|
exprs = append(exprs, function)
|
|
}
|
|
|
|
pushed, remained = PushDownExprs(pushDownCtx, exprs, kv.TiKV)
|
|
require.Len(t, pushed, len(exprs))
|
|
require.Len(t, remained, 0)
|
|
}
|
|
|
|
func TestExprOnlyPushDownToTiKV(t *testing.T) {
|
|
ctx := mock.NewContext()
|
|
client := new(mock.Client)
|
|
pushDownCtx := NewPushDownContextFromSessionVars(ctx, ctx.GetSessionVars(), client)
|
|
|
|
function, err := NewFunction(ctx, "uuid", types.NewFieldType(mysql.TypeLonglong))
|
|
require.NoError(t, err)
|
|
var exprs = make([]Expression, 0)
|
|
exprs = append(exprs, function)
|
|
|
|
pushed, remained := PushDownExprs(pushDownCtx, exprs, kv.UnSpecified)
|
|
require.Len(t, pushed, 1)
|
|
require.Len(t, remained, 0)
|
|
|
|
canPush := CanExprsPushDown(pushDownCtx, exprs, kv.TiFlash)
|
|
require.Equal(t, false, canPush)
|
|
canPush = CanExprsPushDown(pushDownCtx, exprs, kv.TiKV)
|
|
require.Equal(t, true, canPush)
|
|
|
|
pushed, remained = PushDownExprs(pushDownCtx, exprs, kv.TiFlash)
|
|
require.Len(t, pushed, 0)
|
|
require.Len(t, remained, 1)
|
|
pushed, remained = PushDownExprs(pushDownCtx, exprs, kv.TiKV)
|
|
require.Len(t, pushed, 1)
|
|
require.Len(t, remained, 0)
|
|
}
|
|
|
|
func TestGroupByItem2Pb(t *testing.T) {
|
|
ctx := mock.NewContext()
|
|
client := new(mock.Client)
|
|
|
|
item := genColumn(mysql.TypeDouble, 0)
|
|
pbByItem := GroupByItemToPB(ctx, client, item)
|
|
js, err := json.Marshal(pbByItem)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "{\"expr\":{\"tp\":201,\"val\":\"gAAAAAAAAAA=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},\"desc\":false}", string(js))
|
|
|
|
item = genColumn(mysql.TypeDouble, 1)
|
|
pbByItem = GroupByItemToPB(ctx, client, item)
|
|
js, err = json.Marshal(pbByItem)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "{\"expr\":{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},\"desc\":false}", string(js))
|
|
}
|
|
|
|
func TestSortByItem2Pb(t *testing.T) {
|
|
ctx := mock.NewContext()
|
|
client := new(mock.Client)
|
|
|
|
item := genColumn(mysql.TypeDouble, 0)
|
|
pbByItem := SortByItemToPB(ctx, client, item, false)
|
|
js, err := json.Marshal(pbByItem)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "{\"expr\":{\"tp\":201,\"val\":\"gAAAAAAAAAA=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},\"desc\":false}", string(js))
|
|
|
|
item = genColumn(mysql.TypeDouble, 1)
|
|
pbByItem = SortByItemToPB(ctx, client, item, false)
|
|
js, err = json.Marshal(pbByItem)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "{\"expr\":{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},\"desc\":false}", string(js))
|
|
|
|
item = genColumn(mysql.TypeDouble, 1)
|
|
pbByItem = SortByItemToPB(ctx, client, item, true)
|
|
js, err = json.Marshal(pbByItem)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "{\"expr\":{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\",\"array\":false},\"has_distinct\":false},\"desc\":true}", string(js))
|
|
}
|
|
|
|
func TestPushCollationDown(t *testing.T) {
|
|
ctx := mock.NewContext()
|
|
fc, err := NewFunction(ctx, ast.EQ, types.NewFieldType(mysql.TypeUnspecified), genColumn(mysql.TypeVarchar, 0), genColumn(mysql.TypeVarchar, 1))
|
|
require.NoError(t, err)
|
|
client := new(mock.Client)
|
|
|
|
tps := []*types.FieldType{types.NewFieldType(mysql.TypeVarchar), types.NewFieldType(mysql.TypeVarchar)}
|
|
for _, coll := range []string{charset.CollationBin, charset.CollationLatin1, charset.CollationUTF8, charset.CollationUTF8MB4} {
|
|
fc.SetCharsetAndCollation("binary", coll) // only collation matters
|
|
pbExpr, err := ExpressionsToPBList(ctx, []Expression{fc}, client)
|
|
require.NoError(t, err)
|
|
expr, err := PBToExpr(ctx, pbExpr[0], tps)
|
|
require.NoError(t, err)
|
|
_, eColl := expr.CharsetAndCollation()
|
|
require.Equal(t, coll, eColl)
|
|
}
|
|
}
|
|
|
|
func columnCollation(c *Column, chs, coll string) *Column {
|
|
c.RetType.SetCharset(chs)
|
|
c.RetType.SetCollate(coll)
|
|
return c
|
|
}
|
|
|
|
func TestNewCollationsEnabled(t *testing.T) {
|
|
var colExprs []Expression
|
|
ctx := mock.NewContext()
|
|
client := new(mock.Client)
|
|
pushDownCtx := NewPushDownContextFromSessionVars(ctx, ctx.GetSessionVars(), client)
|
|
|
|
colExprs = colExprs[:0]
|
|
colExprs = append(colExprs, genColumn(mysql.TypeVarchar, 1))
|
|
colExprs = append(colExprs, columnCollation(genColumn(mysql.TypeVarchar, 2), "some_invalid_charset", "some_invalid_collation"))
|
|
colExprs = append(colExprs, columnCollation(genColumn(mysql.TypeVarString, 3), "utf8mb4", "utf8mb4_general_ci"))
|
|
colExprs = append(colExprs, columnCollation(genColumn(mysql.TypeString, 4), "utf8mb4", "utf8mb4_0900_ai_ci"))
|
|
colExprs = append(colExprs, columnCollation(genColumn(mysql.TypeVarchar, 5), "utf8", "utf8_bin"))
|
|
colExprs = append(colExprs, columnCollation(genColumn(mysql.TypeVarchar, 6), "utf8", "utf8_unicode_ci"))
|
|
colExprs = append(colExprs, columnCollation(genColumn(mysql.TypeVarchar, 7), "utf8mb4", "utf8mb4_zh_pinyin_tidb_as_cs"))
|
|
pushed, _ := PushDownExprs(pushDownCtx, colExprs, kv.UnSpecified)
|
|
require.Equal(t, len(colExprs), len(pushed))
|
|
pbExprs, err := ExpressionsToPBList(ctx, colExprs, client)
|
|
require.NoError(t, err)
|
|
jsons := []string{
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAAAE=\",\"sig\":0,\"field_type\":{\"tp\":15,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-46,\"charset\":\"utf8mb4\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAAAI=\",\"sig\":0,\"field_type\":{\"tp\":15,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-46,\"charset\":\"some_invalid_charset\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAAAM=\",\"sig\":0,\"field_type\":{\"tp\":253,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-45,\"charset\":\"utf8mb4\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAAAQ=\",\"sig\":0,\"field_type\":{\"tp\":254,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-255,\"charset\":\"utf8mb4\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAAAU=\",\"sig\":0,\"field_type\":{\"tp\":15,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-83,\"charset\":\"utf8\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAAAY=\",\"sig\":0,\"field_type\":{\"tp\":15,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-192,\"charset\":\"utf8\",\"array\":false},\"has_distinct\":false}",
|
|
"{\"tp\":201,\"val\":\"gAAAAAAAAAc=\",\"sig\":0,\"field_type\":{\"tp\":15,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-2048,\"charset\":\"utf8mb4\",\"array\":false},\"has_distinct\":false}",
|
|
}
|
|
for i, pbExpr := range pbExprs {
|
|
require.NotNil(t, pbExprs)
|
|
js, err := json.Marshal(pbExpr)
|
|
require.NoError(t, err)
|
|
require.Equalf(t, jsons[i], string(js), "%v\n", i)
|
|
}
|
|
|
|
item := columnCollation(genColumn(mysql.TypeDouble, 0), "utf8mb4", "utf8mb4_0900_ai_ci")
|
|
pbByItem := GroupByItemToPB(ctx, client, item)
|
|
js, err := json.Marshal(pbByItem)
|
|
require.NoError(t, err)
|
|
require.Equal(t, "{\"expr\":{\"tp\":201,\"val\":\"gAAAAAAAAAA=\",\"sig\":0,\"field_type\":{\"tp\":5,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-255,\"charset\":\"utf8mb4\",\"array\":false},\"has_distinct\":false},\"desc\":false}", string(js))
|
|
}
|
|
|
|
func TestMetadata(t *testing.T) {
|
|
ctx := mock.NewContext()
|
|
client := new(mock.Client)
|
|
|
|
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/pkg/expression/PushDownTestSwitcher", `return("all")`))
|
|
defer func() {
|
|
require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/pkg/expression/PushDownTestSwitcher"))
|
|
}()
|
|
|
|
pc := PbConverter{client: client, ctx: ctx}
|
|
|
|
metadata := new(tipb.InUnionMetadata)
|
|
var err error
|
|
// InUnion flag is false in `BuildCastFunction` when `ScalarFuncSig_CastStringAsInt`
|
|
cast := BuildCastFunction(mock.NewContext(), genColumn(mysql.TypeString, 1), types.NewFieldType(mysql.TypeLonglong))
|
|
require.Equal(t, &tipb.InUnionMetadata{InUnion: false}, cast.(*ScalarFunction).Function.metadata())
|
|
expr := pc.ExprToPB(cast)
|
|
require.Equal(t, tipb.ScalarFuncSig_CastStringAsInt, expr.Sig)
|
|
require.Greater(t, len(expr.Val), 0)
|
|
err = proto.Unmarshal(expr.Val, metadata)
|
|
require.NoError(t, err)
|
|
require.Equal(t, false, metadata.InUnion)
|
|
|
|
// InUnion flag is nil in `BuildCastFunction4Union` when `ScalarFuncSig_CastIntAsString`
|
|
castInUnion := BuildCastFunction4Union(mock.NewContext(), genColumn(mysql.TypeLonglong, 1), types.NewFieldType(mysql.TypeString))
|
|
require.Nil(t, castInUnion.(*ScalarFunction).Function.metadata())
|
|
expr = pc.ExprToPB(castInUnion)
|
|
require.Equal(t, tipb.ScalarFuncSig_CastIntAsString, expr.Sig)
|
|
require.Equal(t, 0, len(expr.Val))
|
|
|
|
// InUnion flag is true in `BuildCastFunction4Union` when `ScalarFuncSig_CastStringAsInt`
|
|
castInUnion = BuildCastFunction4Union(mock.NewContext(), genColumn(mysql.TypeString, 1), types.NewFieldType(mysql.TypeLonglong))
|
|
require.Equal(t, &tipb.InUnionMetadata{InUnion: true}, castInUnion.(*ScalarFunction).Function.metadata())
|
|
expr = pc.ExprToPB(castInUnion)
|
|
require.Equal(t, tipb.ScalarFuncSig_CastStringAsInt, expr.Sig)
|
|
require.Greater(t, len(expr.Val), 0)
|
|
err = proto.Unmarshal(expr.Val, metadata)
|
|
require.NoError(t, err)
|
|
require.Equal(t, true, metadata.InUnion)
|
|
}
|
|
|
|
func TestPushDownSwitcher(t *testing.T) {
|
|
var funcs = make([]Expression, 0)
|
|
ctx := mock.NewContext()
|
|
client := new(mock.Client)
|
|
|
|
cases := []struct {
|
|
name string
|
|
sig tipb.ScalarFuncSig
|
|
enable bool
|
|
}{
|
|
// Note that so far ScalarFuncSigs here are not be pushed down when the failpoint PushDownTestSwitcher
|
|
// is disable, which is the prerequisite to pass this test.
|
|
// Need to be replaced with other non pushed down ScalarFuncSigs if they are pushed down one day.
|
|
{ast.Sin, tipb.ScalarFuncSig_Sin, true},
|
|
{ast.Cos, tipb.ScalarFuncSig_Cos, false},
|
|
{ast.Tan, tipb.ScalarFuncSig_Tan, true},
|
|
}
|
|
var enabled []string
|
|
for _, funcName := range cases {
|
|
args := []Expression{genColumn(mysql.TypeDouble, 1)}
|
|
fc, err := NewFunction(
|
|
mock.NewContext(),
|
|
funcName.name,
|
|
types.NewFieldType(mysql.TypeUnspecified),
|
|
args...,
|
|
)
|
|
require.NoError(t, err)
|
|
funcs = append(funcs, fc)
|
|
if funcName.enable {
|
|
enabled = append(enabled, funcName.name)
|
|
}
|
|
}
|
|
|
|
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/pkg/expression/PushDownTestSwitcher", `return("all")`))
|
|
defer func() {
|
|
require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/pkg/expression/PushDownTestSwitcher"))
|
|
}()
|
|
|
|
pbExprs, err := ExpressionsToPBList(ctx, funcs, client)
|
|
require.NoError(t, err)
|
|
require.Equal(t, len(cases), len(pbExprs))
|
|
for i, pbExpr := range pbExprs {
|
|
require.Equalf(t, cases[i].sig, pbExpr.Sig, "function: %s, sig: %v", cases[i].name, cases[i].sig)
|
|
}
|
|
|
|
// All disabled
|
|
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/pkg/expression/PushDownTestSwitcher", `return("")`))
|
|
pc := PbConverter{client: client, ctx: ctx}
|
|
for i := range funcs {
|
|
pbExpr := pc.ExprToPB(funcs[i])
|
|
require.Nil(t, pbExpr)
|
|
}
|
|
|
|
// Partial enabled
|
|
fpexpr := fmt.Sprintf(`return("%s")`, strings.Join(enabled, ","))
|
|
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/pkg/expression/PushDownTestSwitcher", fpexpr))
|
|
for i := range funcs {
|
|
pbExpr := pc.ExprToPB(funcs[i])
|
|
if !cases[i].enable {
|
|
require.Nil(t, pbExpr)
|
|
continue
|
|
}
|
|
require.Equalf(t, cases[i].sig, pbExpr.Sig, "function: %s, sig: %v", cases[i].name, cases[i].sig)
|
|
}
|
|
}
|
|
|
|
func TestPanicIfPbCodeUnspecified(t *testing.T) {
|
|
args := []Expression{genColumn(mysql.TypeLong, 1), genColumn(mysql.TypeLong, 2)}
|
|
fc, err := NewFunction(
|
|
mock.NewContext(),
|
|
ast.And,
|
|
types.NewFieldType(mysql.TypeUnspecified),
|
|
args...,
|
|
)
|
|
require.NoError(t, err)
|
|
fn := fc.(*ScalarFunction)
|
|
fn.Function.setPbCode(tipb.ScalarFuncSig_Unspecified)
|
|
require.Equal(t, tipb.ScalarFuncSig_Unspecified, fn.Function.PbCode())
|
|
|
|
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/pkg/expression/PanicIfPbCodeUnspecified", "return(true)"))
|
|
defer func() {
|
|
require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/pkg/expression/PanicIfPbCodeUnspecified"))
|
|
}()
|
|
pc := PbConverter{client: new(mock.Client), ctx: mock.NewContext()}
|
|
require.PanicsWithError(t, "unspecified PbCode: *expression.builtinBitAndSig", func() { pc.ExprToPB(fn) })
|
|
}
|
|
|
|
func TestProjectionColumn2Pb(t *testing.T) {
|
|
var colExprs []Expression
|
|
ctx := mock.NewContext()
|
|
client := new(mock.Client)
|
|
|
|
colExprs = append(colExprs, genColumn(mysql.TypeSet, 1))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeShort, 2))
|
|
colExprs = append(colExprs, genColumn(mysql.TypeLong, 3))
|
|
|
|
// TypeSet column can't be converted to PB by default
|
|
_, err := ExpressionsToPBList(ctx, colExprs, client)
|
|
require.Error(t, err)
|
|
|
|
_, err = ProjectionExpressionsToPBList(ctx, colExprs, client)
|
|
require.NoError(t, err)
|
|
}
|