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 28, 2023
1 parent d2105f6 commit ff50cbc
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 0 deletions.
43 changes: 43 additions & 0 deletions mapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,3 +263,46 @@ func (parser *NullParser) Map(src string) (any, error) {
}
return nil, NewErrUnexpectedValue(src)
}

// IntervalParser is a parser to datetime.Interval.
type IntervalParser struct{}

// NewIntervalParser creates IntervalParser.
func NewIntervalParser() *IntervalParser {
return &IntervalParser{}
}

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

// Map is the implementation of Mapper[string] for IntervalParser.
func (*IntervalParser) Map(src string) (any, error) {
parts := strings.Split(src, ",")
if len(parts) != intervalFieldsNumber {
return nil, NewErrUnexpectedValue(src)
}
partsAsInt64 := [intervalFieldsNumber]int64{}
for i, part := range parts {
var err error
if partsAsInt64[i], err = strconv.ParseInt(part, 10, 64); err != nil {
return nil, NewErrUnexpectedValue(src)
}
}
adjust := datetime.Adjust(partsAsInt64[8])
if adjust != datetime.NoneAdjust &&
adjust != datetime.ExcessAdjust && adjust != datetime.LastAdjust {
return nil, NewErrUnexpectedValue(src)
}
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 @@ -218,6 +218,27 @@ func TestParsers(t *testing.T) {
{value: "505", isErr: true},
{value: "nil", isErr: true},
},
NewIntervalParser(): {
// 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
4 changes: 4 additions & 0 deletions tt_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ var parserByTTType = map[TypeName]Mapper[string]{
NewDecimalParser(defaultIgnoreChars, defaultDecSeparators),
NewBoolParser(),
NewDateTimeParser(),
NewIntervalParser(),
NewUUIDParser(),
NewStringParser(), // Always success.
}),
Expand All @@ -74,9 +75,12 @@ var parserByTTType = map[TypeName]Mapper[string]{
NewDecimalParser(defaultIgnoreChars, defaultDecSeparators),
NewBoolParser(),
NewDateTimeParser(),
NewIntervalParser(),
NewUUIDParser(),
NewStringParser(), // Always success.
}),

TypeInterval: NewIntervalParser(),
}

var ttParsers MappersTable = &ParsersTTTable{}
Expand Down
49 changes: 49 additions & 0 deletions tt_helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,18 @@ func TestNewParserFor(t *testing.T) {
{value: "", isNullable: true, expected: ""},
{value: "09b56913-11f0-4fa4-b5d0-901b5efa532a", expected: someUUID},
{value: "2020-08-22T11:27:43.123456789-02:00", expected: dateTime1},
{
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,
},
},
},

TypeScalar: {
Expand All @@ -270,6 +282,43 @@ func TestNewParserFor(t *testing.T) {
{value: "", isNullable: true, expected: ""},
{value: "09b56913-11f0-4fa4-b5d0-901b5efa532a", expected: someUUID},
{value: "2020-08-22T11:27:43.123456789-02:00", expected: dateTime1},
{
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,
},
},
},

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: "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 @@ -36,4 +36,5 @@ const (
TypeVarbinary TypeName = "varbinary"
TypeScalar TypeName = "scalar"
TypeAny TypeName = "any"
TypeInterval TypeName = "interval"
)

0 comments on commit ff50cbc

Please sign in to comment.