Skip to content

Commit

Permalink
expression: fix the fsp of casting json as datetime/duration (#53535)
Browse files Browse the repository at this point in the history
close #53352
  • Loading branch information
YangKeao authored May 25, 2024
1 parent 8f958de commit 45318da
Show file tree
Hide file tree
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
Expand Up @@ -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 {
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions pkg/expression/builtin_cast_vec.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down
12 changes: 10 additions & 2 deletions pkg/types/json_binary.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
12 changes: 12 additions & 0 deletions tests/integrationtest/r/expression/json.result
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Up @@ -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 45318da

Please sign in to comment.