Skip to content

Commit

Permalink
imrpvoe json_arrayagg
Browse files Browse the repository at this point in the history
  • Loading branch information
Kingwl committed Oct 11, 2018
1 parent f372c0a commit 2b4f224
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 15 deletions.
12 changes: 3 additions & 9 deletions executor/aggfuncs/func_json.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ func (e *baseJsonArrayAgg) AppendFinalResult2Chunk(sctx sessionctx.Context, pr P
chk.AppendNull(e.ordinal)
return nil
}
result := json.CreateBinary(p.array)
chk.AppendJSON(e.ordinal, result)

chk.AppendJSON(e.ordinal, json.CreateBinary(p.array))
return nil
}

Expand All @@ -57,13 +57,7 @@ func (e *baseJsonArrayAgg) UpdatePartialResult(sctx sessionctx.Context, rowsInGr
return errors.Trace(err)
}

var finalResult string
finalResult, err = res.ToString()
if err != nil {
return errors.Trace(err)
}

result = append(result, finalResult)
result = append(result, res.GetValue())
}
p.array = append(p.array, result...)
return nil
Expand Down
4 changes: 1 addition & 3 deletions executor/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -869,7 +869,7 @@ func (b *executorBuilder) wrapCastForAggArgs(funcs []*aggregation.AggFuncDesc) {
for _, f := range funcs {
// We do not need to wrap cast upon these functions,
// since the EvalXXX method called by the arg is determined by the corresponding arg type.
if f.Name == ast.AggFuncCount || f.Name == ast.AggFuncMin || f.Name == ast.AggFuncMax || f.Name == ast.AggFuncFirstRow {
if f.Name == ast.AggFuncCount || f.Name == ast.AggFuncMin || f.Name == ast.AggFuncMax || f.Name == ast.AggFuncFirstRow || f.Name == ast.AggFuncJsonArrayAgg {
continue
}
var castFunc func(ctx sessionctx.Context, expr expression.Expression) expression.Expression
Expand All @@ -882,8 +882,6 @@ func (b *executorBuilder) wrapCastForAggArgs(funcs []*aggregation.AggFuncDesc) {
castFunc = expression.WrapWithCastAsString
case types.ETDecimal:
castFunc = expression.WrapWithCastAsDecimal
case types.ETJson:
castFunc = expression.WrapWithCastAsString
default:
panic("should never happen in executorBuilder.wrapCastForAggArgs")
}
Expand Down
1 change: 0 additions & 1 deletion expression/aggregation/descriptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,6 @@ func (a *AggFuncDesc) typeInfer4BitFuncs(ctx sessionctx.Context) {
func (a *AggFuncDesc) typeInfer4JsonFuncs(ctx sessionctx.Context) {
a.RetTp = types.NewFieldType(mysql.TypeJSON)
types.SetBinChsClnFlag(a.RetTp)
a.RetTp.Flag |= mysql.NotNullFlag
}

func (a *AggFuncDesc) evalNullValueInOuterJoin4Count(ctx sessionctx.Context, schema *expression.Schema) (types.Datum, bool) {
Expand Down
4 changes: 2 additions & 2 deletions expression/aggregation/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func (sf *jsonArrayAggFunction) Update(evalCtx *AggEvaluateContext, sc *stmtctx.
return nil
}

// FIXME: what should i do
evalCtx.Value, err = ConcatBinaryJSONArray(evalCtx.Value, value)
if err != nil {
return errors.Trace(err)
}
Expand All @@ -43,7 +43,7 @@ func (sf *jsonArrayAggFunction) Update(evalCtx *AggEvaluateContext, sc *stmtctx.

// GetResult implements Aggregation interface.
func (sf *jsonArrayAggFunction) GetResult(evalCtx *AggEvaluateContext) (d types.Datum) {
d.SetMysqlJSON(evalCtx.Value.GetMysqlJSON())
d.SetValue(evalCtx.Value)
return
}

Expand Down
27 changes: 27 additions & 0 deletions expression/aggregation/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package aggregation
import (
"github.com/pingcap/tidb/sessionctx/stmtctx"
"github.com/pingcap/tidb/types"
"github.com/pingcap/tidb/types/json"
"github.com/pingcap/tidb/util/codec"
"github.com/pingcap/tidb/util/mvmap"
"github.com/pkg/errors"
Expand Down Expand Up @@ -92,3 +93,29 @@ func calculateSum(sc *stmtctx.StatementContext, sum, v types.Datum) (data types.
return data, errors.Errorf("invalid value %v for aggregate", sum.Kind())
}
}

func ConcatBinaryJSONArray(data1, data2 types.Datum) (data types.Datum, err error) {
if data2.Kind() == types.KindMysqlJSON {
a := data2.GetMysqlJSON()
if a.TypeCode == json.TypeCodeArray {
data = types.NewDatum(a)
}
} else {
return data, errors.Errorf("invalid value %v for aggregate", data2.Kind())
}
if err != nil {
return data, errors.Trace(err)
}
if data.IsNull() {
return data1, nil
}

switch data1.Kind() {
case types.KindNull:
return data, nil
case types.KindMysqlJSON:
return types.ComputeConcat(data1, data)
default:
return data, errors.Errorf("invalid value %v for aggregate", data1.Kind())
}
}
13 changes: 13 additions & 0 deletions types/datum_eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package types
import (
"github.com/cznic/mathutil"
"github.com/pingcap/tidb/parser/opcode"
"github.com/pingcap/tidb/types/json"
"github.com/pkg/errors"
)

Expand Down Expand Up @@ -64,3 +65,15 @@ func ComputePlus(a, b Datum) (d Datum, err error) {
_, err = InvOp2(a.GetValue(), b.GetValue(), opcode.Plus)
return d, err
}

func ComputeConcat(a, b Datum) (d Datum, err error) {
if a.Kind() == KindMysqlJSON && b.Kind() == KindMysqlJSON {
arr1 := a.GetMysqlJSON()
arr2 := b.GetMysqlJSON()
if arr1.TypeCode == json.TypeCodeArray && arr2.TypeCode == json.TypeCodeArray {
d.SetMysqlJSON(json.MergeBinary([]json.BinaryJSON{arr1, arr2}))
return d, nil
}
}
return d, errors.Errorf("Invalid concatenate: %v %v", a.GetValue(), b.GetValue())
}
3 changes: 3 additions & 0 deletions types/json/binary.go
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,9 @@ func appendBinary(buf []byte, in interface{}) (TypeCode, []byte, error) {
if err != nil {
return typeCode, nil, errors.Trace(err)
}
case []byte:
typeCode = TypeCodeString
buf = appendBinaryString(buf, hack.String(x))
case string:
typeCode = TypeCodeString
buf = appendBinaryString(buf, x)
Expand Down

0 comments on commit 2b4f224

Please sign in to comment.