Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

copr: bit column support push down to TiKV #31884

Closed
wants to merge 31 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
ae306b9
Bit column support push down to TiKV;
Jan 21, 2022
ced1b5a
Merge branch 'pingcap:master' into master
Jan 21, 2022
2be25de
copr: Bit column support push down to TiKV(#30738)
Jan 21, 2022
3127615
Merge branch 'master' of https://github.com/xiejiandong/tidb
Jan 21, 2022
44d310f
Merge branch 'master' into master
hawkingrei Jan 23, 2022
2d24e20
copr: Bit column support push down to TiKV: support cast/ascii/binary…
Feb 9, 2022
3fbbd5e
Merge branch 'master' of https://github.com/xiejiandong/tidb
Feb 9, 2022
9c72109
Merge branch 'pingcap:master' into master
Feb 10, 2022
7aaf62e
copr: Bit column support push down to TiKV, add test.(pingcap#30738)
Feb 10, 2022
014c448
Merge branch 'master' of https://github.com/xiejiandong/tidb
Feb 10, 2022
fb0c78b
copr: Bit column support push down to TiKV, add test.(pingcap#30738)
Feb 10, 2022
7c54b11
Merge branch 'pingcap:master' into master
Feb 10, 2022
9179639
Merge branch 'pingcap:master' into master
Feb 10, 2022
7d1368a
gofmt update.
Feb 11, 2022
8df7931
Merge branch 'master' into master
Feb 11, 2022
d5e0aee
Merge branch 'master' into master
Feb 14, 2022
940af02
Merge branch 'pingcap:master' into master
Feb 16, 2022
ee268af
Merge branch 'master' into master
Feb 16, 2022
d230c30
Merge branch 'master' into master
Feb 16, 2022
690b384
Merge branch 'master' into master
Feb 16, 2022
bf39c0e
fix test
Yisaer Feb 16, 2022
02c043e
Merge pull request #1 from Yisaer/bit-push-down
Feb 16, 2022
2619cd3
Merge branch 'master' into master
Feb 16, 2022
49014d9
Merge branch 'master' into master
Feb 18, 2022
01cb64c
copr: Add Bit column support push down (#30738)
Feb 18, 2022
fa1ca42
Merge branch 'master' of https://github.com/xiejiandong/tidb
Feb 18, 2022
1fe8d4e
Merge branch 'master' into master
Feb 18, 2022
c610366
copr: modify bit test out format.(#30738)
Feb 19, 2022
dc73d6d
Merge branch 'master' of https://github.com/xiejiandong/tidb
Feb 19, 2022
d8a2a0c
copr: add integration_test (pingcap#30738)
Feb 19, 2022
ee65448
Merge branch 'pingcap:master' into master
Feb 20, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions expression/builtin_cast.go
Original file line number Diff line number Diff line change
Expand Up @@ -1955,9 +1955,16 @@ func WrapWithCastAsString(ctx sessionctx.Context, expr Expression) Expression {
if exprTp.Tp == mysql.TypeNewDecimal && argLen != types.UnspecifiedFsp {
argLen += 3
}

if exprTp.EvalType() == types.ETInt {
argLen = mysql.MaxIntWidth
// For TypeBit, castAsString will make length as int(( bit_len + 7 ) / 8) bytes due to
// TiKV needs the bit's real len during calculating, eg: ascii(bit).
if exprTp.Tp == mysql.TypeBit {
argLen = (exprTp.Flen + 7) / 8
}
Comment on lines +1961 to +1965
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there any testcase to cover this? eg: push ascii bit column down and assert the result.

Copy link
Author

Choose a reason for hiding this comment

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

Ok, I will add it.

}

// Because we can't control the length of cast(float as char) for now, we can't determine the argLen.
if exprTp.Tp == mysql.TypeFloat || exprTp.Tp == mysql.TypeDouble {
argLen = -1
Expand Down
3 changes: 3 additions & 0 deletions expression/constant.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,9 @@ func (c *Constant) EvalInt(ctx sessionctx.Context, row chunk.Row) (int64, bool,
} else if c.GetType().Hybrid() || dt.Kind() == types.KindString {
res, err := dt.ToInt64(ctx.GetSessionVars().StmtCtx)
return res, false, err
} else if dt.Kind() == types.KindMysqlBit {
uintVal, err := dt.GetBinaryLiteral().ToInt(ctx.GetSessionVars().StmtCtx)
return int64(uintVal), false, err
}
return dt.GetInt64(), false, nil
}
Expand Down
2 changes: 1 addition & 1 deletion expression/distsql_builtin.go
Original file line number Diff line number Diff line change
Expand Up @@ -1124,7 +1124,7 @@ func PBToExpr(expr *tipb.Expr, tps []*types.FieldType, sc *stmtctx.StatementCont
return convertUint(expr.Val)
case tipb.ExprType_String:
return convertString(expr.Val, expr.FieldType)
case tipb.ExprType_Bytes:
case tipb.ExprType_Bytes, tipb.ExprType_MysqlBit:
return &Constant{Value: types.NewBytesDatum(expr.Val), RetType: types.NewFieldType(mysql.TypeString)}, nil
case tipb.ExprType_Float32:
return convertFloat(expr.Val, true)
Expand Down
5 changes: 4 additions & 1 deletion expression/expr_to_pb.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ func (pc *PbConverter) encodeDatum(ft *types.FieldType, d types.Datum) (tipb.Exp
case types.KindString, types.KindBinaryLiteral:
tp = tipb.ExprType_String
val = d.GetBytes()
case types.KindMysqlBit:
tp = tipb.ExprType_MysqlBit
val = d.GetBytes()
case types.KindBytes:
tp = tipb.ExprType_Bytes
val = d.GetBytes()
Expand Down Expand Up @@ -179,7 +182,7 @@ func (pc PbConverter) columnToPBExpr(column *Column) *tipb.Expr {
return nil
}
switch column.GetType().Tp {
case mysql.TypeBit, mysql.TypeSet, mysql.TypeGeometry, mysql.TypeUnspecified:
case mysql.TypeSet, mysql.TypeGeometry, mysql.TypeUnspecified:
return nil
case mysql.TypeEnum:
if !IsPushDownEnabled("enum", kv.UnSpecified) {
Expand Down
9 changes: 5 additions & 4 deletions expression/expr_to_pb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,9 @@ func TestColumn2Pb(t *testing.T) {
sc := new(stmtctx.StatementContext)
client := new(mock.Client)

colExprs = append(colExprs, genColumn(mysql.TypeBit, 1))
colExprs = append(colExprs, genColumn(mysql.TypeSet, 2))
colExprs = append(colExprs, genColumn(mysql.TypeGeometry, 4))
colExprs = append(colExprs, genColumn(mysql.TypeUnspecified, 5))
colExprs = append(colExprs, genColumn(mysql.TypeSet, 1))
colExprs = append(colExprs, genColumn(mysql.TypeGeometry, 2))
colExprs = append(colExprs, genColumn(mysql.TypeUnspecified, 3))

pushed, remained := PushDownExprs(sc, colExprs, client, kv.UnSpecified)
require.Len(t, pushed, 0)
Expand Down Expand Up @@ -168,6 +167,7 @@ func TestColumn2Pb(t *testing.T) {
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(sc, colExprs, client, kv.UnSpecified)
require.Len(t, pushed, len(colExprs))
require.Len(t, remained, 0)
Expand Down Expand Up @@ -198,6 +198,7 @@ func TestColumn2Pb(t *testing.T) {
"{\"tp\":201,\"val\":\"gAAAAAAAABY=\",\"sig\":0,\"field_type\":{\"tp\":253,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-46,\"charset\":\"utf8mb4\"},\"has_distinct\":false}",
"{\"tp\":201,\"val\":\"gAAAAAAAABc=\",\"sig\":0,\"field_type\":{\"tp\":254,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-46,\"charset\":\"utf8mb4\"},\"has_distinct\":false}",
"{\"tp\":201,\"val\":\"gAAAAAAAABg=\",\"sig\":0,\"field_type\":{\"tp\":247,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}",
"{\"tp\":201,\"val\":\"gAAAAAAAABk=\",\"sig\":0,\"field_type\":{\"tp\":16,\"flag\":0,\"flen\":-1,\"decimal\":-1,\"collate\":-63,\"charset\":\"binary\"},\"has_distinct\":false}",
}
for i, pbExpr := range pbExprs {
require.NotNil(t, pbExprs)
Expand Down
28 changes: 28 additions & 0 deletions expression/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7043,3 +7043,31 @@ func TestIssue22206(t *testing.T) {
unixTime = time.Unix(5000000000, 0).In(tz).String()[:19]
result.Check(testkit.Rows(unixTime))
}

func TestIssue30738(t *testing.T) {
store, clean := testkit.CreateMockStore(t)
defer clean()
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1;")
tk.MustExec("CREATE TABLE t1 (a int, b bit(8), c bit(1), d bit(24));")
tk.MustExec("insert into t1 values(1, 65, 1, 65);") //A
tk.MustExec("insert into t1 values(2, 53, 0, 53);") //5
tk.MustExec("insert into t1 values(3, 54, 1, 54);") //6

tk.MustQuery("select a from t1 where b+1=54;").Check(testkit.Rows("2"))
tk.MustQuery("select a from t1 where c+1=2;").Check(testkit.Rows("1", "3"))
tk.MustQuery("select a from t1 where d-1=53;").Check(testkit.Rows("3"))

tk.MustQuery("select a from t1 where ascii(b)=65;").Check(testkit.Rows("1"))
tk.MustQuery("select a from t1 where ascii(c)=0;").Check(testkit.Rows("2"))
tk.MustQuery("select a from t1 where ascii(d)=54;").Check(testkit.Rows())

tk.MustQuery("select a from t1 where cast(b as char)='A';").Check(testkit.Rows("1"))
tk.MustQuery("select a from t1 where cast(c as char)='\\1';").Check(testkit.Rows())
tk.MustQuery("select a from t1 where cast(d as char)='\\0\\06';").Check(testkit.Rows("3"))

tk.MustQuery("select a from t1 where concat(b, 'kji')='Akji';").Check(testkit.Rows("1"))
tk.MustQuery("select a from t1 where concat(c, 'kji')='\\0kji';").Check(testkit.Rows("2"))
tk.MustQuery("select a from t1 where concat(d, 'kji')='\\0\\06kji';").Check(testkit.Rows("3"))
}
2 changes: 1 addition & 1 deletion kv/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func (d RequestTypeSupportedChecker) supportExpr(exprType tipb.ExprType) bool {
switch exprType {
case tipb.ExprType_Null, tipb.ExprType_Int64, tipb.ExprType_Uint64, tipb.ExprType_String, tipb.ExprType_Bytes,
tipb.ExprType_MysqlDuration, tipb.ExprType_MysqlTime, tipb.ExprType_MysqlDecimal,
tipb.ExprType_Float32, tipb.ExprType_Float64, tipb.ExprType_ColumnRef, tipb.ExprType_MysqlEnum:
tipb.ExprType_Float32, tipb.ExprType_Float64, tipb.ExprType_ColumnRef, tipb.ExprType_MysqlEnum, tipb.ExprType_MysqlBit:
return true
// aggregate functions.
// NOTE: tipb.ExprType_GroupConcat is only supported by TiFlash, So checking it for TiKV case outside.
Expand Down
5 changes: 5 additions & 0 deletions planner/core/expression_rewriter.go
Original file line number Diff line number Diff line change
Expand Up @@ -1132,6 +1132,11 @@ func (er *expressionRewriter) Leave(originInNode ast.Node) (retNode ast.Node, ok
} else {
castFunction.SetRepertoire(expression.UNICODE)
}

//See detailed comment in `expression/builtin_cast.go:WrapWithCastAsString()`; eg: "where CAST(bit as CAHR)"
if arg.GetType().Tp == mysql.TypeBit {
Copy link
Member

Choose a reason for hiding this comment

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

Why we still need to add this if block after we added the same codes in the WrapWithCastAsString?

Copy link
Author

@xiejiandong xiejiandong Feb 18, 2022

Choose a reason for hiding this comment

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

Function ascii()、concat() will call through expression/builtin_cast.go::WrapWithCastAsString;
Function cast()、binary() will call through planner/core/expression_rewriter.go::Leave;
The two kinds of functions be called not the same way, so there are two positions needed to be updated.
And I don't know is there any other position need to update. So by copr-test, I only updated the 2 positions and passed the test; Maybe we can update them in the future.

v.Tp.Flen = (arg.GetType().Flen + 7) / 8
}
} else {
castFunction.SetCoercibility(expression.CoercibilityNumeric)
castFunction.SetRepertoire(expression.ASCII)
Expand Down
8 changes: 6 additions & 2 deletions planner/core/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2521,8 +2521,8 @@ func (s *testIntegrationSerialSuite) TestIssue18984(c *C) {
func (s *testIntegrationSuite) TestScalarFunctionPushDown(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("create table t(id int signed, id2 int unsigned ,c varchar(11), d datetime, b double)")
tk.MustExec("insert into t(id,c,d) values (1,'abc','2021-12-12')")
tk.MustExec("create table t(id int signed, id2 int unsigned, c varchar(11), d datetime, b double, bit_col bit(1))")
tk.MustExec("insert into t(id,c,d,bit_col) values (1, 'abc','2021-12-12', 1)")
rows := [][]interface{}{
{"TableReader_7", "root", "data:Selection_6"},
{"└─Selection_6", "cop[tikv]", "right(test.t.c, 1)"},
Expand Down Expand Up @@ -2576,6 +2576,10 @@ func (s *testIntegrationSuite) TestScalarFunctionPushDown(c *C) {
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where atan2(id,id);").
CheckAt([]int{0, 3, 6}, rows)

rows[1][2] = "ascii(cast(test.t.bit_col, var_string(1)))"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where ascii(bit_col);").
CheckAt([]int{0, 3, 6}, rows)

rows[1][2] = "hour(cast(test.t.d, time))"
tk.MustQuery("explain analyze select /*+read_from_storage(tikv[t])*/ * from t where hour(d);").
CheckAt([]int{0, 3, 6}, rows)
Expand Down
4 changes: 1 addition & 3 deletions planner/core/testdata/point_get_plan_out.json
Original file line number Diff line number Diff line change
Expand Up @@ -191,9 +191,7 @@
{
"SQL": "select * from t5 where id in ('0')",
"Plan": [
"Selection 8000.00 root eq(test.t5.id, 0)",
"└─TableReader 10000.00 root data:TableFullScan",
" └─TableFullScan 10000.00 cop[tikv] table:t5 keep order:false, stats:pseudo"
"Point_Get 1.00 root table:t5, clustered index:PRIMARY(id) "
],
"Res": null
}
Expand Down
6 changes: 3 additions & 3 deletions util/ranger/testdata/ranger_suite_out.json
Original file line number Diff line number Diff line change
Expand Up @@ -408,9 +408,9 @@
{
"SQL": "select * from t where a = 0;",
"Plan": [
"Selection_7 0.80 root eq(test.t.a, 0)",
"└─TableReader_9 1.00 root data:TableFullScan_8",
" └─TableFullScan_8 1.00 cop[tikv] table:t, partition:p0 keep order:false"
"TableReader_9 1.00 root data:Selection_8",
"└─Selection_8 1.00 cop[tikv] eq(test.t.a, 0)",
" └─TableFullScan_7 1.00 cop[tikv] table:t, partition:p0 keep order:false"
],
"Result": [
"\u0000 0"
Expand Down