Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
expression: fix the fsp of casting json as datetime/duration (pingcap…
Browse files Browse the repository at this point in the history
YangKeao authored and RidRisR committed May 27, 2024
1 parent ff52bf2 commit 00ee739
Showing 5 changed files with 36 additions and 8 deletions.
8 changes: 4 additions & 4 deletions pkg/expression/builtin_cast.go
Original file line number Diff line number Diff line change
@@ -518,7 +518,7 @@ func (b *castJSONAsArrayFunctionSig) evalJSON(ctx EvalContext, row chunk.Row) (r
return types.CreateBinaryJSON(arrayVals), false, nil
}

// ConvertJSON2Tp returns a function that can convert JSON to the specified type.
// ConvertJSON2Tp converts JSON to the specified type.
func ConvertJSON2Tp(v types.BinaryJSON, targetType *types.FieldType) (any, error) {
convertFunc := convertJSON2Tp(targetType.EvalType())
if convertFunc == nil {
@@ -560,7 +560,7 @@ func convertJSON2Tp(evalType types.EvalType) func(*stmtctx.StatementContext, typ
if (tp.GetType() == mysql.TypeDatetime && item.TypeCode != types.JSONTypeCodeDatetime) || (tp.GetType() == mysql.TypeDate && item.TypeCode != types.JSONTypeCodeDate) {
return nil, ErrInvalidJSONForFuncIndex
}
res := item.GetTime()
res := item.GetTimeWithFsp(tp.GetDecimal())
res.SetType(tp.GetType())
if tp.GetType() == mysql.TypeDate {
// Truncate hh:mm:ss part if the type is Date.
@@ -1929,7 +1929,7 @@ func (b *builtinCastJSONAsTimeSig) evalTime(ctx EvalContext, row chunk.Row) (res

switch val.TypeCode {
case types.JSONTypeCodeDate, types.JSONTypeCodeDatetime, types.JSONTypeCodeTimestamp:
res = val.GetTime()
res = val.GetTimeWithFsp(b.tp.GetDecimal())
res.SetType(b.tp.GetType())
if b.tp.GetType() == mysql.TypeDate {
// Truncate hh:mm:ss part if the type is Date.
@@ -1991,7 +1991,7 @@ func (b *builtinCastJSONAsDurationSig) evalDuration(ctx EvalContext, row chunk.R

switch val.TypeCode {
case types.JSONTypeCodeDate, types.JSONTypeCodeDatetime, types.JSONTypeCodeTimestamp:
time := val.GetTime()
time := val.GetTimeWithFsp(b.tp.GetDecimal())
res, err = time.ConvertToDuration()
if err != nil {
return res, false, err
4 changes: 2 additions & 2 deletions pkg/expression/builtin_cast_vec.go
Original file line number Diff line number Diff line change
@@ -508,7 +508,7 @@ func (b *builtinCastJSONAsTimeSig) vecEvalTime(ctx EvalContext, input *chunk.Chu

switch val.TypeCode {
case types.JSONTypeCodeDate, types.JSONTypeCodeDatetime, types.JSONTypeCodeTimestamp:
tm := val.GetTime()
tm := val.GetTimeWithFsp(b.tp.GetDecimal())
times[i] = tm
times[i].SetType(b.tp.GetType())
if b.tp.GetType() == mysql.TypeDate {
@@ -1975,7 +1975,7 @@ func (b *builtinCastJSONAsDurationSig) vecEvalDuration(ctx EvalContext, input *c

switch val.TypeCode {
case types.JSONTypeCodeDate, types.JSONTypeCodeDatetime, types.JSONTypeCodeTimestamp:
time := val.GetTime()
time := val.GetTimeWithFsp(b.tp.GetDecimal())
d, err := time.ConvertToDuration()
if err != nil {
return err
12 changes: 10 additions & 2 deletions pkg/types/json_binary.go
Original file line number Diff line number Diff line change
@@ -237,8 +237,16 @@ func (bj BinaryJSON) GetOpaque() Opaque {
}
}

// GetTime gets the time value
// GetTime gets the time value with default fsp
//
// Deprecated: use GetTimeWithFsp instead. The `BinaryJSON` doesn't contain the fsp information, so the caller
// should always provide the fsp.
func (bj BinaryJSON) GetTime() Time {
return bj.GetTimeWithFsp(DefaultFsp)
}

// GetTimeWithFsp gets the time value with given fsp
func (bj BinaryJSON) GetTimeWithFsp(fsp int) Time {
coreTime := CoreTime(bj.GetUint64())

tp := mysql.TypeDate
@@ -248,7 +256,7 @@ func (bj BinaryJSON) GetTime() Time {
tp = mysql.TypeTimestamp
}

return NewTime(coreTime, tp, DefaultFsp)
return NewTime(coreTime, tp, fsp)
}

// GetDuration gets the duration value
12 changes: 12 additions & 0 deletions tests/integrationtest/r/expression/json.result
Original file line number Diff line number Diff line change
@@ -649,3 +649,15 @@ select 1 from t where cast(BINARY vc as json) = '1';
1
select 1 from t where cast(BINARY c as json) = '1';
1
drop table if exists t;
create table t (j json);
insert into t values (cast(cast("2024-10-24 11:11:11.12346" as datetime(6)) as json));
select cast(j as datetime(6)) from t;
cast(j as datetime(6))
2024-10-24 11:11:11.123460
select cast(j as datetime(3)) from t;
cast(j as datetime(3))
2024-10-24 11:11:11.123
select cast(j as datetime) from t;
cast(j as datetime)
2024-10-24 11:11:11
8 changes: 8 additions & 0 deletions tests/integrationtest/t/expression/json.test
Original file line number Diff line number Diff line change
@@ -393,3 +393,11 @@ select 1 from t where cast(vc as json) = '1';
select 1 from t where cast(c as json) = '1';
select 1 from t where cast(BINARY vc as json) = '1';
select 1 from t where cast(BINARY c as json) = '1';

# TestCastJSONToTimeWithCorrectFsp
drop table if exists t;
create table t (j json);
insert into t values (cast(cast("2024-10-24 11:11:11.12346" as datetime(6)) as json));
select cast(j as datetime(6)) from t;
select cast(j as datetime(3)) from t;
select cast(j as datetime) from t;

0 comments on commit 00ee739

Please sign in to comment.