Skip to content

Commit

Permalink
tupleconv: add tt interval type.
Browse files Browse the repository at this point in the history
Added support for the tarantool `interval` type:

- implemented a parser for this format. Currently, the supported format is
the order of interval fields  from most significant to least significant, as follows:
`year,month,week,day,hour,min,sec,nsec,adjust`.

- added the `interval` type to the table of tarantool types, and now the parsing
of interval is used for parsing `any` and `scalar` types.
  • Loading branch information
askalt committed Jul 30, 2023
1 parent 34c0e94 commit 059f9cc
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 10 deletions.
54 changes: 51 additions & 3 deletions mapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ package tupleconv

import (
"encoding/json"
"errors"
"fmt"
"github.com/google/uuid"
"github.com/tarantool/go-tarantool/v2/datetime"
"github.com/tarantool/go-tarantool/v2/decimal"
"strconv"
"strings"
"time"

"github.com/google/uuid"
"github.com/tarantool/go-tarantool/v2/datetime"
"github.com/tarantool/go-tarantool/v2/decimal"
)

// Mapper is a mapper from S to T.
Expand All @@ -30,6 +32,7 @@ var (
_ Mapper[string, any] = (*StringToSliceMapper)(nil)
_ Mapper[string, any] = (*StringToNullMapper)(nil)
_ Mapper[string, any] = (*IdentityMapper[string])(nil)
_ Mapper[string, any] = (*StringToIntervalMapper)(nil)
)

type IdentityMapper[S any] struct{}
Expand Down Expand Up @@ -257,3 +260,48 @@ func (mapper StringToNullMapper) Map(src string) (any, error) {
}
return nil, nil
}

// StringToIntervalMapper is a mapper from string to datetime.Interval.
type StringToIntervalMapper struct{}

// MakeStringToIntervalMapper creates StringToIntervalMapper.
func MakeStringToIntervalMapper() StringToIntervalMapper {
return StringToIntervalMapper{}
}

// intervalFieldsNumber is the number of fields in datetime.Interval.
const intervalFieldsNumber = 9

var errUnexpectedIntervalFmt = errors.New("unexpected interval format")

// Map is the implementation of Mapper[string] for StringToIntervalMapper.
func (StringToIntervalMapper) Map(src string) (any, error) {
parts := strings.Split(src, ",")
if len(parts) != intervalFieldsNumber {
return nil, errUnexpectedIntervalFmt
}
partsAsInt64 := [intervalFieldsNumber]int64{}
for i, part := range parts {
var err error
if partsAsInt64[i], err = strconv.ParseInt(part, 10, 64); err != nil {
return nil, errUnexpectedIntervalFmt
}
}
adjust := datetime.Adjust(partsAsInt64[8])
if adjust != datetime.NoneAdjust &&
adjust != datetime.ExcessAdjust && adjust != datetime.LastAdjust {
return nil, errUnexpectedIntervalFmt
}
interval := datetime.Interval{
Year: partsAsInt64[0],
Month: partsAsInt64[1],
Week: partsAsInt64[2],
Day: partsAsInt64[3],
Hour: partsAsInt64[4],
Min: partsAsInt64[5],
Sec: partsAsInt64[6],
Nsec: partsAsInt64[7],
Adjust: adjust,
}
return interval, nil
}
21 changes: 21 additions & 0 deletions mapper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,27 @@ func TestParsers(t *testing.T) {
{value: "505", isErr: true},
{value: "nil", isErr: true},
},
tupleconv.MakeStringToIntervalMapper(): {
// Basic.
{
value: "1,2,3,4,5,6,7,8,1",
expected: datetime.Interval{
Year: 1, Month: 2, Week: 3, Day: 4, Hour: 5, Min: 6, Sec: 7, Nsec: 8, Adjust: 1,
},
},
{
value: "-11,-1110,0,0,0,0,0,1,2",
expected: datetime.Interval{
Year: -11, Month: -1110, Nsec: 1, Adjust: 2,
},
},

// Error.
{value: "1,2,3,4,5,6,7,8,3", isErr: true}, // Invalid adjust.
{value: "1,2,3", isErr: true},
{value: "1,2,3,4,5,6,7a,8,0", isErr: true},
{value: "", isErr: true},
},
}

for parser, cases := range tests {
Expand Down
3 changes: 3 additions & 0 deletions tt.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ func makeStringToTTMappers(opts StringToTTMapperOpts) map[TypeName]Mapper[string
MakeStringToBoolMapper(),
MakeStringToDateTimeMapper(),
MakeStringToUUIDMapper(),
MakeStringToIntervalMapper(),
MakeIdentityMapper[string](), // Always success.
}),

Expand All @@ -72,10 +73,12 @@ func makeStringToTTMappers(opts StringToTTMapperOpts) map[TypeName]Mapper[string
MakeStringToBoolMapper(),
MakeStringToDateTimeMapper(),
MakeStringToUUIDMapper(),
MakeStringToIntervalMapper(),
MakeIdentityMapper[string](), // Always success.
}),

TypeNullable: MakeStringToNullMapper(opts.NullValue),
TypeInterval: MakeStringToIntervalMapper(),
}

return result
Expand Down
44 changes: 37 additions & 7 deletions tt_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package tupleconv_test

import (
"math/big"
"reflect"
"testing"
"time"

"github.com/google/uuid"
dec "github.com/shopspring/decimal"
"github.com/stretchr/testify/assert"
Expand All @@ -9,10 +14,6 @@ import (
"github.com/tarantool/go-tarantool/v2/datetime"
"github.com/tarantool/go-tarantool/v2/decimal"
"github.com/tarantool/go-tupleconv"
"math/big"
"reflect"
"testing"
"time"
)

type ttTestCase struct {
Expand Down Expand Up @@ -351,6 +352,18 @@ func TestTTBasic(t *testing.T) {
{value: "09b56913-11f0-4fa4-b5d0-901b5efa532a", expected: someUUID},
{value: "2020-08-22T11:27:43.123456789-02:00", expected: dateTime1},
{value: "1`e2", expected: "1`e2"},
{
value: "1,2,3,4,5,6,7,8,1",
expected: datetime.Interval{
Year: 1, Month: 2, Week: 3, Day: 4, Hour: 5, Min: 6, Sec: 7, Nsec: 8, Adjust: 1,
},
},
{
value: "-11,-1110,0,0,0,0,0,1,2",
expected: datetime.Interval{
Year: -11, Month: -1110, Nsec: 1, Adjust: 2,
},
},
},

tupleconv.TypeScalar: {
Expand All @@ -377,14 +390,31 @@ func TestTTBasic(t *testing.T) {
-9223372036854775808)),
0)},
{value: "1.447e+44", expected: dec.NewFromBigInt(big.NewInt(1447), 41)},
},

tupleconv.TypeInterval: {
// Basic.
{
value: "1,2,3,4,5,6,7,8,1",
expected: datetime.Interval{
Year: 1, Month: 2, Week: 3, Day: 4, Hour: 5, Min: 6, Sec: 7, Nsec: 8, Adjust: 1,
},
},
{
value: "-11,-1110,0,0,0,0,0,1,2",
expected: datetime.Interval{
Year: -11, Month: -1110, Nsec: 1, Adjust: 2,
},
},

// Nullable.
{value: "", isNullable: true, expected: nil},

// Error.
{value: "abacaba", isErr: true},
{value: "-1/0", isErr: true},
{value: "1**5", isErr: true},
{value: "1,2,3,4,5,6,7,8,3", isErr: true}, // Invalid adjust.
{value: "1,2,3", isErr: true},
{value: "1,2,3,4,5,6,7a,8,0", isErr: true},
{value: "", isErr: true},
},
}

Expand Down
1 change: 1 addition & 0 deletions tt_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,5 @@ const (
TypeScalar TypeName = "scalar"
TypeAny TypeName = "any"
TypeNullable TypeName = "nullable"
TypeInterval TypeName = "interval"
)

0 comments on commit 059f9cc

Please sign in to comment.