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

expression, plan: support builtin aggregation function 'bit_xor' #5090

Merged
merged 26 commits into from
Dec 5, 2017
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
c6af0fd
Support aggregation function 'BIT_XOR'
spongedu Nov 13, 2017
d611830
expression, plan: support builtin aggregation function 'bit_xor'
spongedu Nov 13, 2017
7ca774e
Merge remote-tracking branch 'upstream/master' into agg_bit_xor
spongedu Nov 13, 2017
4b9aab4
Fix build fail
spongedu Nov 13, 2017
d09cba0
Merge branch 'master' into agg_bit_xor
spongedu Nov 14, 2017
e2b3523
Merge branch 'master' into agg_bit_xor
zz-jason Nov 16, 2017
b36a765
Code Format Refine
spongedu Nov 18, 2017
70a3325
Merge remote-tracking branch 'upstream/master' into agg_bit_xor
spongedu Nov 18, 2017
497ede5
Fix build fail
spongedu Nov 18, 2017
fd37344
Merge remote-tracking branch 'upstream/master' into agg_bit_xor
spongedu Nov 18, 2017
9ce3871
Change type to uint64
spongedu Nov 18, 2017
c7568b7
Merge branch 'master' into agg_bit_xor
coocood Nov 21, 2017
8237c71
Merge branch 'master' into agg_bit_xor
coocood Nov 21, 2017
1891dbf
Fix build fail
spongedu Nov 22, 2017
442bc94
Merge remote-tracking branch 'upstream/master' into agg_bit_xor
spongedu Nov 22, 2017
5a77e7b
Fix build fail due to code merge
spongedu Nov 22, 2017
44295ea
Merge branch 'master' into agg_bit_xor
spongedu Nov 22, 2017
bb7b176
Merge branch 'master' into agg_bit_xor
spongedu Nov 23, 2017
40d0d6f
disabled `bit_xor` in `store/tikv/coprocessor.go`
spongedu Nov 23, 2017
94a1adb
Merge remote-tracking branch 'upstream/master' into agg_bit_xor
spongedu Nov 24, 2017
69d0348
Merge branch 'master' into agg_bit_xor
spongedu Nov 29, 2017
12943e8
Merge branch 'master' into agg_bit_xor
spongedu Dec 1, 2017
d0aba7a
Merge branch 'master' into agg_bit_xor
zz-jason Dec 4, 2017
e876916
Merge branch 'master' into agg_bit_xor
coocood Dec 5, 2017
534fcd6
Merge branch 'master' into agg_bit_xor
coocood Dec 5, 2017
d1e0e73
Merge branch 'master' into agg_bit_xor
coocood Dec 5, 2017
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

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions ast/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,8 @@ const (
AggFuncMin = "min"
// AggFuncGroupConcat is the name of group_concat function.
AggFuncGroupConcat = "group_concat"
// AggFuncBitXor is the name of bit_xor function.
AggFuncBitXor = "bit_xor"
)

// AggregateFuncExpr represents aggregate function expression.
Expand Down
2 changes: 2 additions & 0 deletions expression/aggregation/agg_to_pb.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ func AggFuncToPBExpr(sc *variable.StatementContext, client kv.Client, aggFunc Ag
tp = tipb.ExprType_Sum
case ast.AggFuncAvg:
tp = tipb.ExprType_Avg
case ast.AggFuncBitXor:
tp = tipb.ExprType_AggBitXor
}
if !client.IsRequestTypeSupported(kv.ReqTypeSelect, int64(tp)) {
return nil
Expand Down
4 changes: 4 additions & 0 deletions expression/aggregation/aggregation.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ func NewAggFunction(funcType string, funcArgs []expression.Expression, distinct
return &maxMinFunction{aggFunction: newAggFunc(tp, funcArgs, distinct), isMax: false}
case ast.AggFuncFirstRow:
return &firstRowFunction{aggFunction: newAggFunc(tp, funcArgs, distinct)}
case ast.AggFuncBitXor:
return &bitXorFunction{aggFunction: newAggFunc(tp, funcArgs, distinct)}
}
return nil
}
Expand Down Expand Up @@ -125,6 +127,8 @@ func NewDistAggFunc(expr *tipb.Expr, fieldTps []*types.FieldType, sc *variable.S
return &maxMinFunction{aggFunction: newAggFunc(ast.AggFuncMin, args, false)}, nil
case tipb.ExprType_First:
return &firstRowFunction{aggFunction: newAggFunc(ast.AggFuncFirstRow, args, false)}, nil
case tipb.ExprType_AggBitXor:
return &bitXorFunction{aggFunction: newAggFunc(ast.AggFuncBitXor, args, false)}, nil
}
return nil, errors.Errorf("Unknown aggregate function type %v", expr.Tp)
}
Expand Down
97 changes: 97 additions & 0 deletions expression/aggregation/bit_xor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package aggregation

import (
"github.com/juju/errors"
"github.com/pingcap/tidb/context"
"github.com/pingcap/tidb/expression"
"github.com/pingcap/tidb/mysql"
"github.com/pingcap/tidb/sessionctx/variable"
"github.com/pingcap/tidb/types"
)

type bitXorFunction struct {
aggFunction
}

// Clone implements Aggregation interface.
func (bf *bitXorFunction) Clone() Aggregation {
nf := *bf
for i, arg := range bf.Args {
nf.Args[i] = arg.Clone()
}
return &nf
}

// CalculateDefaultValue implements Aggregation interface.
func (bf *bitXorFunction) CalculateDefaultValue(schema *expression.Schema, ctx context.Context) (d types.Datum, valid bool) {
arg := bf.Args[0]
result := expression.EvaluateExprWithNull(ctx, schema, arg)
if con, ok := result.(*expression.Constant); ok {
if con.Value.IsNull() {
return types.NewDatum(0), true
}
return con.Value, true
}
return types.NewDatum(0), true
}

// GetType implements Aggregation interface.
func (bf *bitXorFunction) GetType() *types.FieldType {
ft := types.NewFieldType(mysql.TypeLonglong)
ft.Flen = 21
types.SetBinChsClnFlag(ft)
return ft
}

// Update implements Aggregation interface.
func (bf *bitXorFunction) Update(ctx *AggEvaluateContext, sc *variable.StatementContext, row types.Row) error {
if bf.mode == CompleteMode {
if len(bf.Args) == 0 {
return nil
} else if len(bf.Args) != 1 {
return errors.New("Wrong number of args for AggFuncBitXor")
}
a := bf.Args[0]
value, err := a.Eval(row)
if err != nil {
return errors.Trace(err)
}
if ctx.Value.IsNull() {
ctx.Value.SetInt64(0)
}
if !value.IsNull() {
ctx.Value.SetInt64(ctx.Value.GetInt64() ^ value.GetInt64())
}
} else {
if ctx.Value.IsNull() {
ctx.Value.SetInt64(0)
}
v, _ := row.GetInt64(0)
ctx.Value.SetInt64(ctx.Value.GetInt64() ^ v)
}
return nil
}

// GetResult implements Aggregation interface.
func (bf *bitXorFunction) GetResult(ctx *AggEvaluateContext) (d types.Datum) {
d.SetInt64(ctx.Value.GetInt64())
return d
}

// GetPartialResult implements Aggregation interface.
func (bf *bitXorFunction) GetPartialResult(ctx *AggEvaluateContext) []types.Datum {
return []types.Datum{bf.GetResult(ctx)}
}
25 changes: 25 additions & 0 deletions expression/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2601,6 +2601,31 @@ func (s *testIntegrationSuite) TestAggregationBuiltin(c *C) {
result.Check(testkit.Rows("1.1234560000"))
}

func (s *testIntegrationSuite) TestAggregationBuiltinBitXor(c *C) {
defer s.cleanEnv(c)
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t;")
tk.MustExec("create table t(a bigint)")
tk.MustExec("insert into t values(null);")
result := tk.MustQuery("select bit_xor(a) from t")
result.Check(testkit.Rows("0"))
tk.MustExec("insert into t values(1);")
result = tk.MustQuery("select bit_xor(a) from t")
result.Check(testkit.Rows("1"))
tk.MustExec("insert into t values(2);")
result = tk.MustQuery("select bit_xor(a) from t")
result.Check(testkit.Rows("3"))
tk.MustExec("insert into t values(3);")
result = tk.MustQuery("select bit_xor(a) from t")
result.Check(testkit.Rows("0"))
tk.MustExec("insert into t values(3);")
result = tk.MustQuery("select bit_xor(a) from t")
result.Check(testkit.Rows("3"))
result = tk.MustQuery("select a, bit_xor(a) from t group by a order by a")
result.Check(testkit.Rows("<nil> 0", "1 1", "2 2", "3 0"))
}

func (s *testIntegrationSuite) TestOtherBuiltin(c *C) {
defer s.cleanEnv(c)
tk := testkit.NewTestKit(c, s.store)
Expand Down
3 changes: 2 additions & 1 deletion plan/physical_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,8 @@ func needCount(af aggregation.Aggregation) bool {

func needValue(af aggregation.Aggregation) bool {
return af.GetName() == ast.AggFuncSum || af.GetName() == ast.AggFuncAvg || af.GetName() == ast.AggFuncFirstRow ||
af.GetName() == ast.AggFuncMax || af.GetName() == ast.AggFuncMin || af.GetName() == ast.AggFuncGroupConcat
af.GetName() == ast.AggFuncMax || af.GetName() == ast.AggFuncMin || af.GetName() == ast.AggFuncGroupConcat ||
af.GetName() == ast.AggFuncBitXor
}

// PhysicalTableScan represents a table scan plan.
Expand Down
2 changes: 1 addition & 1 deletion store/tikv/coprocessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func (c *CopClient) supportExpr(exprType tipb.ExprType) bool {
case tipb.ExprType_Case, tipb.ExprType_If, tipb.ExprType_IfNull, tipb.ExprType_Coalesce:
return true
// aggregate functions.
case tipb.ExprType_Count, tipb.ExprType_First, tipb.ExprType_Max, tipb.ExprType_Min, tipb.ExprType_Sum, tipb.ExprType_Avg:
case tipb.ExprType_Count, tipb.ExprType_First, tipb.ExprType_Max, tipb.ExprType_Min, tipb.ExprType_Sum, tipb.ExprType_Avg, tipb.ExprType_AggBitXor:
return true
// json functions.
case tipb.ExprType_JsonType, tipb.ExprType_JsonExtract, tipb.ExprType_JsonUnquote,
Expand Down